1#![allow(unused_imports)]
2use super::super::arithmetic::div_mod::{rust_div, rust_rem};
3use super::super::prelude::*;
4use super::super::wrapping::*;
5
6use core::cmp::Ordering;
7
8verus! {
9
10pub open spec fn next_multiple_of(x: int, y: int) -> int
13 recommends
14 y > 0,
15{
16 if x % y == 0 {
17 x
18 } else {
19 x + (y - x % y)
20 }
21}
22
23} macro_rules! num_specs {
25 ($uN: ty, $iN: ty, $mod_u_tmp:ident, $mod_i_tmp:ident, $mod_u:ident, $mod_i:ident, $range:expr) => {
26 verus! {
27
28 mod $mod_u_tmp {
33 use super::*;
34
35 pub assume_specification[<$uN as Clone>::clone](x: &$uN) -> (res: $uN)
36 ensures res == x;
37
38 impl super::super::cmp::PartialEqSpecImpl for $uN {
39 open spec fn obeys_eq_spec() -> bool {
40 true
41 }
42
43 open spec fn eq_spec(&self, other: &$uN) -> bool {
44 *self == *other
45 }
46 }
47
48 impl super::super::cmp::PartialOrdSpecImpl for $uN {
49 open spec fn obeys_partial_cmp_spec() -> bool {
50 true
51 }
52
53 open spec fn partial_cmp_spec(&self, other: &$uN) -> Option<Ordering> {
54 if *self < *other {
55 Some(Ordering::Less)
56 } else if *self > *other {
57 Some(Ordering::Greater)
58 } else {
59 Some(Ordering::Equal)
60 }
61 }
62 }
63
64 impl super::super::cmp::OrdSpecImpl for $uN {
65 open spec fn obeys_cmp_spec() -> bool {
66 true
67 }
68
69 open spec fn cmp_spec(&self, other: &$uN) -> Ordering {
70 if *self < *other {
71 Ordering::Less
72 } else if *self > *other {
73 Ordering::Greater
74 } else {
75 Ordering::Equal
76 }
77 }
78 }
79
80 pub assume_specification[<$uN as PartialEq<$uN>>::eq](x: &$uN, y: &$uN) -> bool;
81
82 pub assume_specification[<$uN as PartialEq<$uN>>::ne](x: &$uN, y: &$uN) -> bool;
83
84 pub assume_specification[<$uN as Ord>::cmp](x: &$uN, y: &$uN) -> Ordering;
85
86 pub assume_specification[<$uN as PartialOrd<$uN>>::partial_cmp](x: &$uN, y: &$uN) -> Option<Ordering>;
87
88 pub assume_specification[<$uN as PartialOrd<$uN>>::lt](x: &$uN, y: &$uN) -> bool;
89
90 pub assume_specification[<$uN as PartialOrd<$uN>>::le](x: &$uN, y: &$uN) -> bool;
91
92 pub assume_specification[<$uN as PartialOrd<$uN>>::gt](x: &$uN, y: &$uN) -> bool;
93
94 pub assume_specification[<$uN as PartialOrd<$uN>>::ge](x: &$uN, y: &$uN) -> bool;
95
96 #[verifier::allow_in_spec]
97 #[cfg(not(verus_verify_core))]
98 pub assume_specification[<$uN>::wrapping_add](x: $uN, y: $uN) -> $uN
99 returns $mod_u::wrapping_add(x, y)
100 opens_invariants none
101 no_unwind;
102
103 #[verifier::allow_in_spec]
104 #[cfg(not(verus_verify_core))]
105 pub assume_specification[<$uN>::wrapping_add_signed](x: $uN, y: $iN) -> $uN
106 returns $mod_u::wrapping_add_signed(x, y)
107 opens_invariants none
108 no_unwind;
109
110 #[verifier::allow_in_spec]
111 #[cfg(not(verus_verify_core))]
112 pub assume_specification[<$uN>::wrapping_sub](x: $uN, y: $uN) -> $uN
113 returns $mod_u::wrapping_sub(x, y)
114 opens_invariants none
115 no_unwind;
116
117 #[verifier::allow_in_spec]
118 #[cfg(not(verus_verify_core))]
119 pub assume_specification[<$uN>::wrapping_mul](x: $uN, y: $uN) -> $uN
120 returns $mod_u::wrapping_mul(x, y)
121 opens_invariants none
122 no_unwind;
123
124 #[verifier::allow_in_spec]
125 #[cfg(not(verus_verify_core))]
126 pub assume_specification[<$uN>::wrapping_shl](x: $uN, rhs: u32) -> $uN
127 returns $mod_u::wrapping_shl(x, rhs)
128 opens_invariants none
129 no_unwind;
130
131 #[verifier::allow_in_spec]
132 #[cfg(not(verus_verify_core))]
133 pub assume_specification[<$uN>::wrapping_shr](x: $uN, rhs: u32) -> $uN
134 returns $mod_u::wrapping_shr(x, rhs)
135 opens_invariants none
136 no_unwind;
137
138 #[verifier::allow_in_spec]
139 #[cfg(not(verus_verify_core))]
140 pub assume_specification[<$uN>::checked_add](x: $uN, y: $uN) -> Option<$uN>
141 returns (
142 if x + y > <$uN>::MAX {
143 None
144 } else {
145 Some((x + y) as $uN)
146 }
147 );
148
149 #[verifier::allow_in_spec]
150 #[cfg(not(verus_verify_core))]
151 pub assume_specification[<$uN>::checked_add_signed](x: $uN, y: $iN) -> Option<$uN>
152 returns (
153 if x + y > <$uN>::MAX || x + y < 0 {
154 None
155 } else {
156 Some((x + y) as $uN)
157 }
158 );
159
160 #[verifier::allow_in_spec]
161 #[cfg(not(verus_verify_core))]
162 pub assume_specification[<$uN>::checked_sub](x: $uN, y: $uN) -> Option<$uN>
163 returns (
164 if x - y < 0 {
165 None
166 } else {
167 Some((x - y) as $uN)
168 }
169 );
170
171 #[verifier::allow_in_spec]
172 #[cfg(not(verus_verify_core))]
173 pub assume_specification[<$uN>::checked_mul](x: $uN, y: $uN) -> Option<$uN>
174 returns (
175 if x * y > <$uN>::MAX {
176 None
177 } else {
178 Some((x * y) as $uN)
179 }
180 );
181
182 #[verifier::allow_in_spec]
183 #[cfg(not(verus_verify_core))]
184 pub assume_specification[<$uN>::checked_next_multiple_of](x: $uN, rhs: $uN) -> Option<$uN>
185 returns (
186 if rhs == 0 {
187 None
188 } else if next_multiple_of(x as int, rhs as int) > <$uN>::MAX {
189 None
190 } else {
191 Some(next_multiple_of(x as int, rhs as int) as $uN)
192 }
193 );
194
195 pub open spec fn checked_div(x: $uN, y: $uN) -> Option<$uN> {
196 if y == 0 {
197 None
198 } else {
199 Some(x / y)
200 }
201 }
202
203 #[verifier::when_used_as_spec(checked_div)]
204 #[cfg(not(verus_verify_core))]
205 pub assume_specification[<$uN>::checked_div](lhs: $uN, rhs: $uN) -> (result: Option<$uN>)
206 ensures
207 result == checked_div(lhs, rhs);
208
209 #[verifier::when_used_as_spec(checked_div)]
210 #[cfg(not(verus_verify_core))]
211 pub assume_specification[<$uN>::checked_div_euclid](lhs: $uN, rhs: $uN) -> (result: Option<$uN>)
212 ensures
213 result == checked_div(lhs, rhs);
215
216 #[verifier::allow_in_spec]
217 #[cfg(not(verus_verify_core))]
218 pub assume_specification[<$uN>::checked_rem](lhs: $uN, rhs: $uN) -> Option<$uN>
219 returns (
220 if rhs == 0 {
221 None
222 }
223 else {
224 Some((lhs % rhs) as $uN)
225 }
226 );
227
228 #[verifier::allow_in_spec]
229 #[cfg(not(verus_verify_core))]
230 pub assume_specification[<$uN>::checked_rem_euclid](lhs: $uN, rhs: $uN) -> Option<$uN>
231 returns (
232 if rhs == 0 {
233 None
234 }
235 else {
236 Some((lhs % rhs) as $uN)
237 }
238 );
239
240 #[verifier::allow_in_spec]
241 #[cfg(not(verus_verify_core))]
242 pub assume_specification[<$uN>::saturating_add](x: $uN, y: $uN) -> $uN
243 returns (
244 if x + y > <$uN>::MAX {
245 <$uN>::MAX
246 } else {
247 (x + y) as $uN
248 }
249 );
250
251 #[verifier::allow_in_spec]
252 #[cfg(not(verus_verify_core))]
253 pub assume_specification[<$uN>::saturating_sub](x: $uN, y: $uN) -> $uN
254 returns (
255 if x - y < <$uN>::MIN {
256 <$uN>::MIN
257 } else {
258 (x - y) as $uN
259 }
260 );
261
262 #[verifier::allow_in_spec]
263 #[cfg(not(verus_verify_core))]
264 pub assume_specification[<$uN>::is_multiple_of](x: $uN, y: $uN) -> bool
265 returns (
266 if y == 0 { x == 0 } else { x % y == 0 }
267 );
268 }
269
270 mod $mod_i_tmp {
273 use super::*;
274
275 pub assume_specification[<$iN as Clone>::clone](x: &$iN) -> (res: $iN)
276 ensures res == x;
277
278 impl super::super::cmp::PartialEqSpecImpl for $iN {
279 open spec fn obeys_eq_spec() -> bool {
280 true
281 }
282
283 open spec fn eq_spec(&self, other: &$iN) -> bool {
284 *self == *other
285 }
286 }
287
288 impl super::super::cmp::PartialOrdSpecImpl for $iN {
289 open spec fn obeys_partial_cmp_spec() -> bool {
290 true
291 }
292
293 open spec fn partial_cmp_spec(&self, other: &$iN) -> Option<Ordering> {
294 if *self < *other {
295 Some(Ordering::Less)
296 } else if *self > *other {
297 Some(Ordering::Greater)
298 } else {
299 Some(Ordering::Equal)
300 }
301 }
302 }
303
304 impl super::super::cmp::OrdSpecImpl for $iN {
305 open spec fn obeys_cmp_spec() -> bool {
306 true
307 }
308
309 open spec fn cmp_spec(&self, other: &$iN) -> Ordering {
310 if *self < *other {
311 Ordering::Less
312 } else if *self > *other {
313 Ordering::Greater
314 } else {
315 Ordering::Equal
316 }
317 }
318 }
319
320 pub assume_specification[<$iN as PartialEq<$iN>>::eq](x: &$iN, y: &$iN) -> bool;
321
322 pub assume_specification[<$iN as PartialEq<$iN>>::ne](x: &$iN, y: &$iN) -> bool;
323
324 pub assume_specification[<$iN as Ord>::cmp](x: &$iN, y: &$iN) -> Ordering;
325
326 pub assume_specification[<$iN as PartialOrd<$iN>>::partial_cmp](x: &$iN, y: &$iN) -> Option<Ordering>;
327
328 pub assume_specification[<$iN as PartialOrd<$iN>>::lt](x: &$iN, y: &$iN) -> bool;
329
330 pub assume_specification[<$iN as PartialOrd<$iN>>::le](x: &$iN, y: &$iN) -> bool;
331
332 pub assume_specification[<$iN as PartialOrd<$iN>>::gt](x: &$iN, y: &$iN) -> bool;
333
334 pub assume_specification[<$iN as PartialOrd<$iN>>::ge](x: &$iN, y: &$iN) -> bool;
335
336 #[verifier::allow_in_spec]
337 #[cfg(not(verus_verify_core))]
338 pub assume_specification[<$iN>::wrapping_add](x: $iN, y: $iN) -> $iN
339 returns $mod_i::wrapping_add(x, y)
340 opens_invariants none
341 no_unwind;
342
343 #[verifier::allow_in_spec]
344 #[cfg(not(verus_verify_core))]
345 pub assume_specification[<$iN>::wrapping_add_unsigned](x: $iN, y: $uN) -> $iN
346 returns $mod_i::wrapping_add_unsigned(x, y)
347 opens_invariants none
348 no_unwind;
349
350 #[verifier::allow_in_spec]
351 #[cfg(not(verus_verify_core))]
352 pub assume_specification[<$iN>::wrapping_sub](x: $iN, y: $iN) -> (res: $iN)
353 returns $mod_i::wrapping_sub(x, y)
354 opens_invariants none
355 no_unwind;
356
357 #[verifier::allow_in_spec]
358 #[cfg(not(verus_verify_core))]
359 pub assume_specification[<$iN>::wrapping_mul](x: $iN, y: $iN) -> $iN
360 returns $mod_i::wrapping_mul(x, y)
361 opens_invariants none
362 no_unwind;
363
364 #[verifier::allow_in_spec]
365 #[cfg(not(verus_verify_core))]
366 pub assume_specification[<$iN>::wrapping_shl](x: $iN, rhs: u32) -> $iN
367 returns $mod_i::wrapping_shl(x, rhs)
368 opens_invariants none
369 no_unwind;
370
371 #[verifier::allow_in_spec]
372 #[cfg(not(verus_verify_core))]
373 pub assume_specification[<$iN>::wrapping_shr](x: $iN, rhs: u32) -> $iN
374 returns $mod_i::wrapping_shr(x, rhs)
375 opens_invariants none
376 no_unwind;
377
378 #[verifier::allow_in_spec]
379 #[cfg(not(verus_verify_core))]
380 pub assume_specification[<$iN>::checked_add](x: $iN, y: $iN) -> Option<$iN>
381 returns (
382 if x + y > <$iN>::MAX || x + y < <$iN>::MIN {
383 None
384 } else {
385 Some((x + y) as $iN)
386 }
387 );
388
389 #[verifier::allow_in_spec]
390 #[cfg(not(verus_verify_core))]
391 pub assume_specification[<$iN>::checked_add_unsigned](x: $iN, y: $uN) -> Option<$iN>
392 returns (
393 if x + y > <$iN>::MAX {
394 None
395 } else {
396 Some((x + y) as $iN)
397 }
398 );
399
400 #[verifier::allow_in_spec]
401 #[cfg(not(verus_verify_core))]
402 pub assume_specification[<$iN>::checked_sub](x: $iN, y: $iN) -> Option<$iN>
403 returns (
404 if x - y > <$iN>::MAX || x - y < <$iN>::MIN {
405 None
406 } else {
407 Some((x - y) as $iN)
408 }
409 );
410
411 #[verifier::allow_in_spec]
412 #[cfg(not(verus_verify_core))]
413 pub assume_specification[<$iN>::checked_sub_unsigned](x: $iN, y: $uN) -> Option<$iN>
414 returns (
415 if x - y < <$iN>::MIN {
416 None
417 } else {
418 Some((x - y) as $iN)
419 }
420 );
421
422 #[verifier::allow_in_spec]
423 #[cfg(not(verus_verify_core))]
424 pub assume_specification[<$iN>::checked_mul](x: $iN, y: $iN) -> Option<$iN>
425 returns (
426 if x * y > <$iN>::MAX || x * y < <$iN>::MIN {
427 None
428 } else {
429 Some((x * y) as $iN)
430 }
431 );
432
433 #[verifier::allow_in_spec]
434 #[cfg(not(verus_verify_core))]
435 pub assume_specification[<$iN>::checked_div](lhs: $iN, rhs: $iN) -> Option<$iN>
436 returns (
437 if rhs == 0 || (lhs == <$iN>::MIN && rhs == -1) {
438 None
439 } else {
440 Some(rust_div(lhs as int, rhs as int) as $iN)
441 }
442 );
443
444 #[verifier::allow_in_spec]
445 #[cfg(not(verus_verify_core))]
446 pub assume_specification[<$iN>::checked_div_euclid](lhs: $iN, rhs: $iN) -> Option<$iN>
447 returns (
448 if rhs == 0 || (lhs == <$iN>::MIN && rhs == -1) {
449 None
450 } else {
451 Some((lhs / rhs) as $iN)
452 }
453 );
454
455 #[verifier::allow_in_spec]
456 #[cfg(not(verus_verify_core))]
457 pub assume_specification[<$iN>::checked_rem](lhs: $iN, rhs: $iN) -> Option<$iN>
458 returns (
459 if rhs == 0 || (lhs == <$iN>::MIN && rhs == -1) {
460 None
461 } else {
462 Some(rust_rem(lhs as int, rhs as int) as $iN)
463 }
464 );
465
466 #[verifier::allow_in_spec]
467 #[cfg(not(verus_verify_core))]
468 pub assume_specification[<$iN>::checked_rem_euclid](lhs: $iN, rhs: $iN) -> Option<$iN>
469 returns (
470 if rhs == 0 || (lhs == <$iN>::MIN && rhs == -1) {
471 None
472 } else {
473 Some((lhs % rhs) as $iN)
474 }
475 );
476 }
477
478 }
479 };
480}
481
482num_specs!(u8, i8, u8_specs_tmp, i8_specs_tmp, u8_specs, i8_specs, 0x100);
483num_specs!(u16, i16, u16_specs_tmp, i16_specs_tmp, u16_specs, i16_specs, 0x1_0000);
484num_specs!(u32, i32, u32_specs_tmp, i32_specs_tmp, u32_specs, i32_specs, 0x1_0000_0000);
485num_specs!(u64, i64, u64_specs_tmp, i64_specs_tmp, u64_specs, i64_specs, 0x1_0000_0000_0000_0000);
486num_specs!(
487 u128,
488 i128,
489 u128_specs_tmp,
490 i128_specs_tmp,
491 u128_specs,
492 i128_specs,
493 0x1_0000_0000_0000_0000_0000_0000_0000_0000
494);
495num_specs!(
496 usize,
497 isize,
498 usize_specs_tmp,
499 isize_specs_tmp,
500 usize_specs,
501 isize_specs,
502 (usize::MAX - usize::MIN + 1)
503);