1use crate::prelude::{Clone, Default, *};
29use core::cmp::Ordering;
30
31#[derive(Default, Clone, Copy, Eq)]
35#[non_exhaustive]
36#[repr(transparent)]
37pub struct PeanoInt(pub u64);
38
39impl DeepModel for PeanoInt {
40 type DeepModelTy = u64;
41 #[logic(open, inline)]
42 fn deep_model(self) -> u64 {
43 self.0
44 }
45}
46
47impl PartialOrdLogic for PeanoInt {
48 #[logic(open, inline)]
49 fn lt_log(self, o: Self) -> bool {
50 self.0 < o.0
51 }
52
53 #[logic(open, inline)]
54 fn le_log(self, o: Self) -> bool {
55 self.0 <= o.0
56 }
57
58 #[logic]
59 #[ensures(!(self < self))]
60 fn irreflexive(self) {}
61
62 #[logic]
63 #[requires(x < y)]
64 #[requires(y < z)]
65 #[ensures(x < z)]
66 fn transitive(x: Self, y: Self, z: Self) {}
67
68 #[logic]
69 #[ensures((self <= other) == (self < other || self == other))]
70 fn le_lt_log(self, other: Self) {}
71}
72
73impl OrdLogic for PeanoInt {
74 #[logic]
75 #[ensures(self < other || self == other || other < self)]
76 fn lt_log_total(self, other: Self) {}
77}
78
79impl View for PeanoInt {
80 type ViewTy = u64;
81 #[logic(open, inline)]
82 fn view(self) -> u64 {
83 self.0
84 }
85}
86
87impl PartialOrd for PeanoInt {
88 #[check(ghost)]
89 #[ensures(result == Some((*self).cmp_log(*other)))]
90 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
91 Some(self.cmp(other))
92 }
93
94 #[check(ghost)]
98 #[ensures(result == (self@ < other@))]
99 fn lt(&self, other: &Self) -> bool {
100 matches!(self.partial_cmp(other), Some(Ordering::Less))
101 }
102 #[check(ghost)]
103 #[ensures(result == (self@ <= other@))]
104 fn le(&self, other: &Self) -> bool {
105 matches!(self.partial_cmp(other), Some(Ordering::Less | Ordering::Equal))
106 }
107 #[check(ghost)]
108 #[ensures(result == (self@ > other@))]
109 fn gt(&self, other: &Self) -> bool {
110 matches!(self.partial_cmp(other), Some(Ordering::Greater))
111 }
112 #[check(ghost)]
113 #[ensures(result == (self@ >= other@))]
114 fn ge(&self, other: &Self) -> bool {
115 matches!(self.partial_cmp(other), Some(Ordering::Greater | Ordering::Equal))
116 }
117}
118impl Ord for PeanoInt {
119 #[check(ghost)]
120 #[ensures(result == (*self).cmp_log(*other))]
121 fn cmp(&self, other: &Self) -> Ordering {
122 self.0.cmp(&other.0)
123 }
124}
125impl PartialEq for PeanoInt {
126 #[check(ghost)]
127 #[ensures(result == (*self == *other))]
128 fn eq(&self, other: &Self) -> bool {
129 self.0 == other.0
130 }
131}
132
133impl PeanoInt {
134 #[check(ghost)]
136 #[ensures(result.0 == 0u64)]
137 pub fn new() -> Self {
138 Self(0)
139 }
140
141 #[trusted]
156 #[check(terminates)]
157 #[ensures(result.0@ == self.0@ + 1)]
158 pub fn incr(self) -> Self {
159 let x = unsafe { core::ptr::read_volatile(&self.0) };
162 Self(x + 1)
163 }
164
165 #[check(ghost)]
167 #[ensures(result == self.0)]
168 pub fn to_u64(self) -> u64 {
169 self.0
170 }
171
172 #[check(ghost)]
174 #[trusted]
175 #[ensures(result@ == self.0@)]
176 pub fn to_i64(self) -> i64 {
177 self.0 as i64
178 }
179
180 #[check(ghost)]
182 #[ensures(result@ == self.0@)]
183 pub fn to_u128(self) -> u128 {
184 self.0 as u128
185 }
186
187 #[check(ghost)]
189 #[ensures(result@ == self.0@)]
190 pub fn to_i128(self) -> i128 {
191 self.0 as i128
192 }
193}
194
195impl From<PeanoInt> for u64 {
196 #[check(ghost)]
197 #[ensures(result == val.0)]
198 fn from(val: PeanoInt) -> Self {
199 val.to_u64()
200 }
201}
202
203impl From<PeanoInt> for i64 {
204 #[check(ghost)]
205 #[ensures(result@ == val.0@)]
206 fn from(val: PeanoInt) -> Self {
207 val.to_i64()
208 }
209}
210
211impl From<PeanoInt> for u128 {
212 #[check(ghost)]
213 #[ensures(result@ == val.0@)]
214 fn from(val: PeanoInt) -> Self {
215 val.to_u128()
216 }
217}
218
219impl From<PeanoInt> for i128 {
220 #[check(ghost)]
221 #[ensures(result@ == val.0@)]
222 fn from(val: PeanoInt) -> Self {
223 val.to_i128()
224 }
225}