1#![forbid(unsafe_code)]
17#![allow(clippy::too_many_arguments)]
18#![cfg_attr(test, allow(clippy::assertions_on_result_states))]
19
20extern crate snarkvm_console_types_integers as console;
21
22mod helpers;
23
24pub mod abs_checked;
25pub mod abs_wrapped;
26pub mod add_checked;
27pub mod add_wrapped;
28pub mod and;
29pub mod compare;
30pub mod div_checked;
31pub mod div_wrapped;
32pub mod equal;
33pub mod modulo;
34pub mod mul_checked;
35pub mod mul_wrapped;
36pub mod neg;
37pub mod not;
38pub mod or;
39pub mod pow_checked;
40pub mod pow_wrapped;
41pub mod rem_checked;
42pub mod rem_wrapped;
43pub mod shl_checked;
44pub mod shl_wrapped;
45pub mod shr_checked;
46pub mod shr_wrapped;
47pub mod sub_checked;
48pub mod sub_wrapped;
49pub mod ternary;
50pub mod xor;
51
52pub type I8<E> = Integer<E, i8>;
53pub type I16<E> = Integer<E, i16>;
54pub type I32<E> = Integer<E, i32>;
55pub type I64<E> = Integer<E, i64>;
56pub type I128<E> = Integer<E, i128>;
57
58pub type U8<E> = Integer<E, u8>;
59pub type U16<E> = Integer<E, u16>;
60pub type U32<E> = Integer<E, u32>;
61pub type U64<E> = Integer<E, u64>;
62pub type U128<E> = Integer<E, u128>;
63
64#[cfg(test)]
65use snarkvm_circuit_environment::{
66 assert_count,
67 assert_count_fails,
68 assert_output_mode,
69 assert_scope,
70 count,
71 output_mode,
72};
73#[cfg(test)]
74use snarkvm_utilities::{TestRng, Uniform};
75
76use snarkvm_circuit_environment::prelude::*;
77use snarkvm_circuit_types_boolean::Boolean;
78use snarkvm_circuit_types_field::Field;
79use snarkvm_circuit_types_scalar::Scalar;
80
81use core::marker::PhantomData;
82
83#[derive(Clone)]
84pub struct Integer<E: Environment, I: IntegerType> {
85 bits_le: Vec<Boolean<E>>,
86 phantom: PhantomData<I>,
87}
88
89impl<E: Environment, I: IntegerType> IntegerTrait<I, U8<E>, U16<E>, U32<E>> for Integer<E, I> {}
90
91impl<E: Environment, I: IntegerType> IntegerCore<I> for Integer<E, I> {}
92
93impl<E: Environment, I: IntegerType> Integer<E, I> {
94 pub fn size_in_bits() -> u16 {
96 I::BITS as u16
97 }
98
99 pub fn cast_as_dual(self) -> Integer<E, I::Dual> {
101 Integer::<E, I::Dual> { bits_le: self.bits_le, phantom: Default::default() }
102 }
103}
104
105impl<E: Environment, I: IntegerType> Inject for Integer<E, I> {
106 type Primitive = console::Integer<E::Network, I>;
107
108 fn new(mode: Mode, value: Self::Primitive) -> Self {
110 let mut bits_le = Vec::with_capacity(I::BITS as usize);
111 let mut value = *value;
112 for _ in 0..I::BITS {
113 bits_le.push(Boolean::new(mode, value & I::one() == I::one()));
114 value = value.wrapping_shr(1u32);
115 }
116 Self::from_bits_le(&bits_le)
117 }
118}
119
120impl<E: Environment, I: IntegerType> Eject for Integer<E, I> {
121 type Primitive = console::Integer<E::Network, I>;
122
123 fn eject_mode(&self) -> Mode {
125 self.bits_le.eject_mode()
126 }
127
128 fn eject_value(&self) -> Self::Primitive {
130 self.bits_le.iter().rev().fold(console::Integer::zero(), |value, bit| match bit.eject_value() {
131 true => console::Integer::new((value.wrapping_shl(1)) ^ I::one()),
132 false => console::Integer::new((value.wrapping_shl(1)) ^ I::zero()),
133 })
134 }
135}
136
137impl<E: Environment, I: IntegerType> Parser for Integer<E, I> {
138 #[inline]
140 fn parse(string: &str) -> ParserResult<Self> {
141 let (string, integer) = console::Integer::parse(string)?;
143 let (string, mode) = opt(pair(tag("."), Mode::parse))(string)?;
145
146 match mode {
147 Some((_, mode)) => Ok((string, Integer::new(mode, integer))),
148 None => Ok((string, Integer::new(Mode::Constant, integer))),
149 }
150 }
151}
152
153impl<E: Environment, I: IntegerType> FromStr for Integer<E, I> {
154 type Err = Error;
155
156 #[inline]
158 fn from_str(string: &str) -> Result<Self> {
159 match Self::parse(string) {
160 Ok((remainder, object)) => {
161 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
163 Ok(object)
165 }
166 Err(error) => bail!("Failed to parse string. {error}"),
167 }
168 }
169}
170
171impl<E: Environment, I: IntegerType> TypeName for Integer<E, I> {
172 #[inline]
174 fn type_name() -> &'static str {
175 console::Integer::<E::Network, I>::type_name()
176 }
177}
178
179impl<E: Environment, I: IntegerType> Debug for Integer<E, I> {
180 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181 Display::fmt(self, f)
182 }
183}
184
185impl<E: Environment, I: IntegerType> Display for Integer<E, I> {
186 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187 write!(f, "{}.{}", self.eject_value(), self.eject_mode())
188 }
189}
190
191impl<E: Environment, I: IntegerType> From<Integer<E, I>> for LinearCombination<E::BaseField> {
192 fn from(integer: Integer<E, I>) -> Self {
193 From::from(&integer)
194 }
195}
196
197impl<E: Environment, I: IntegerType> From<&Integer<E, I>> for LinearCombination<E::BaseField> {
198 fn from(integer: &Integer<E, I>) -> Self {
199 let mut accumulator = E::zero();
201 let mut coefficient = E::BaseField::one();
202 for bit in &integer.bits_le {
203 accumulator += LinearCombination::from(bit) * coefficient;
204 coefficient = coefficient.double();
205 }
206 accumulator
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213 use snarkvm_circuit_environment::Circuit;
214
215 const ITERATIONS: u64 = 10;
216
217 fn check_new<I: IntegerType>(
218 mode: Mode,
219 num_constants: u64,
220 num_public: u64,
221 num_private: u64,
222 num_constraints: u64,
223 rng: &mut TestRng,
224 ) {
225 for _ in 0..ITERATIONS {
226 let expected = Uniform::rand(rng);
227
228 Circuit::scope(format!("New {mode}"), || {
229 let candidate = Integer::<Circuit, I>::new(mode, expected);
230 assert_eq!(mode, candidate.eject_mode());
231 assert_eq!(expected, candidate.eject_value());
232 assert_scope!(num_constants, num_public, num_private, num_constraints);
233 })
234 }
235 assert_eq!(console::Integer::MIN, Integer::<Circuit, I>::new(mode, console::Integer::MIN).eject_value());
237 assert_eq!(console::Integer::MAX, Integer::<Circuit, I>::new(mode, console::Integer::MAX).eject_value());
238 }
239
240 fn check_parse<I: IntegerType>(
241 mode: Mode,
242 num_constants: u64,
243 num_public: u64,
244 num_private: u64,
245 num_constraints: u64,
246 rng: &mut TestRng,
247 ) {
248 for _ in 0..ITERATIONS {
249 let value = Uniform::rand(rng);
250 let expected = Integer::<Circuit, I>::new(mode, value);
251
252 Circuit::scope(format!("Parse {mode}"), || {
253 let (_, candidate) = Integer::<Circuit, I>::parse(&format!("{expected}")).unwrap();
254 assert_eq!((mode, value), candidate.eject());
255 assert_eq!(expected.eject_mode(), candidate.eject_mode());
256 assert_eq!(expected.eject_value(), candidate.eject_value());
257 assert_scope!(num_constants, num_public, num_private, num_constraints);
258 })
259 }
260 }
261
262 fn check_display<I: IntegerType>() {
263 let candidate = Integer::<Circuit, I>::new(Mode::Constant, console::Integer::one() + console::Integer::one());
265 assert_eq!(format!("2{}.constant", I::type_name()), format!("{candidate}"));
266
267 let candidate = Integer::<Circuit, I>::new(Mode::Public, console::Integer::one() + console::Integer::one());
269 assert_eq!(format!("2{}.public", I::type_name()), format!("{candidate}"));
270
271 let candidate = Integer::<Circuit, I>::new(Mode::Private, console::Integer::one() + console::Integer::one());
273 assert_eq!(format!("2{}.private", I::type_name()), format!("{candidate}"));
274 }
275
276 #[test]
279 fn test_u8_new() {
280 let mut rng = TestRng::default();
281
282 check_new::<u8>(Mode::Constant, 8, 0, 0, 0, &mut rng);
283 check_new::<u8>(Mode::Public, 0, 8, 0, 8, &mut rng);
284 check_new::<u8>(Mode::Private, 0, 0, 8, 8, &mut rng);
285 }
286
287 #[test]
288 fn test_u8_parse() {
289 let mut rng = TestRng::default();
290
291 check_parse::<u8>(Mode::Constant, 8, 0, 0, 0, &mut rng);
292 check_parse::<u8>(Mode::Public, 0, 8, 0, 8, &mut rng);
293 check_parse::<u8>(Mode::Private, 0, 0, 8, 8, &mut rng);
294 }
295
296 #[test]
297 fn test_u8_display() {
298 check_display::<u8>();
299 }
300
301 #[test]
304 fn test_i8_new() {
305 let mut rng = TestRng::default();
306
307 check_new::<i8>(Mode::Constant, 8, 0, 0, 0, &mut rng);
308 check_new::<i8>(Mode::Public, 0, 8, 0, 8, &mut rng);
309 check_new::<i8>(Mode::Private, 0, 0, 8, 8, &mut rng);
310 }
311
312 #[test]
313 fn test_i8_parse() {
314 let mut rng = TestRng::default();
315
316 check_parse::<i8>(Mode::Constant, 8, 0, 0, 0, &mut rng);
317 check_parse::<i8>(Mode::Public, 0, 8, 0, 8, &mut rng);
318 check_parse::<i8>(Mode::Private, 0, 0, 8, 8, &mut rng);
319 }
320
321 #[test]
322 fn test_i8_display() {
323 check_display::<i8>();
324 }
325
326 #[test]
329 fn test_u16_new() {
330 let mut rng = TestRng::default();
331
332 check_new::<u16>(Mode::Constant, 16, 0, 0, 0, &mut rng);
333 check_new::<u16>(Mode::Public, 0, 16, 0, 16, &mut rng);
334 check_new::<u16>(Mode::Private, 0, 0, 16, 16, &mut rng);
335 }
336
337 #[test]
338 fn test_u16_parse() {
339 let mut rng = TestRng::default();
340
341 check_parse::<u16>(Mode::Constant, 16, 0, 0, 0, &mut rng);
342 check_parse::<u16>(Mode::Public, 0, 16, 0, 16, &mut rng);
343 check_parse::<u16>(Mode::Private, 0, 0, 16, 16, &mut rng);
344 }
345
346 #[test]
347 fn test_u16_display() {
348 check_display::<u16>();
349 }
350
351 #[test]
354 fn test_i16_new() {
355 let mut rng = TestRng::default();
356
357 check_new::<i16>(Mode::Constant, 16, 0, 0, 0, &mut rng);
358 check_new::<i16>(Mode::Public, 0, 16, 0, 16, &mut rng);
359 check_new::<i16>(Mode::Private, 0, 0, 16, 16, &mut rng);
360 }
361
362 #[test]
363 fn test_i16_parse() {
364 let mut rng = TestRng::default();
365
366 check_parse::<i16>(Mode::Constant, 16, 0, 0, 0, &mut rng);
367 check_parse::<i16>(Mode::Public, 0, 16, 0, 16, &mut rng);
368 check_parse::<i16>(Mode::Private, 0, 0, 16, 16, &mut rng);
369 }
370
371 #[test]
372 fn test_i16_display() {
373 check_display::<i16>();
374 }
375
376 #[test]
379 fn test_u32_new() {
380 let mut rng = TestRng::default();
381
382 check_new::<u32>(Mode::Constant, 32, 0, 0, 0, &mut rng);
383 check_new::<u32>(Mode::Public, 0, 32, 0, 32, &mut rng);
384 check_new::<u32>(Mode::Private, 0, 0, 32, 32, &mut rng);
385 }
386
387 #[test]
388 fn test_u32_parse() {
389 let mut rng = TestRng::default();
390
391 check_parse::<u32>(Mode::Constant, 32, 0, 0, 0, &mut rng);
392 check_parse::<u32>(Mode::Public, 0, 32, 0, 32, &mut rng);
393 check_parse::<u32>(Mode::Private, 0, 0, 32, 32, &mut rng);
394 }
395
396 #[test]
397 fn test_u32_display() {
398 check_display::<u32>();
399 }
400
401 #[test]
404 fn test_i32_new() {
405 let mut rng = TestRng::default();
406
407 check_new::<i32>(Mode::Constant, 32, 0, 0, 0, &mut rng);
408 check_new::<i32>(Mode::Public, 0, 32, 0, 32, &mut rng);
409 check_new::<i32>(Mode::Private, 0, 0, 32, 32, &mut rng);
410 }
411
412 #[test]
413 fn test_i32_parse() {
414 let mut rng = TestRng::default();
415
416 check_parse::<i32>(Mode::Constant, 32, 0, 0, 0, &mut rng);
417 check_parse::<i32>(Mode::Public, 0, 32, 0, 32, &mut rng);
418 check_parse::<i32>(Mode::Private, 0, 0, 32, 32, &mut rng);
419 }
420
421 #[test]
422 fn test_i32_display() {
423 check_display::<i32>();
424 }
425
426 #[test]
429 fn test_u64_new() {
430 let mut rng = TestRng::default();
431
432 check_new::<u64>(Mode::Constant, 64, 0, 0, 0, &mut rng);
433 check_new::<u64>(Mode::Public, 0, 64, 0, 64, &mut rng);
434 check_new::<u64>(Mode::Private, 0, 0, 64, 64, &mut rng);
435 }
436
437 #[test]
438 fn test_u64_parse() {
439 let mut rng = TestRng::default();
440
441 check_parse::<u64>(Mode::Constant, 64, 0, 0, 0, &mut rng);
442 check_parse::<u64>(Mode::Public, 0, 64, 0, 64, &mut rng);
443 check_parse::<u64>(Mode::Private, 0, 0, 64, 64, &mut rng);
444 }
445
446 #[test]
447 fn test_u64_display() {
448 check_display::<u64>();
449 }
450
451 #[test]
454 fn test_i64_new() {
455 let mut rng = TestRng::default();
456
457 check_new::<i64>(Mode::Constant, 64, 0, 0, 0, &mut rng);
458 check_new::<i64>(Mode::Public, 0, 64, 0, 64, &mut rng);
459 check_new::<i64>(Mode::Private, 0, 0, 64, 64, &mut rng);
460 }
461
462 #[test]
463 fn test_i64_parse() {
464 let mut rng = TestRng::default();
465
466 check_parse::<i64>(Mode::Constant, 64, 0, 0, 0, &mut rng);
467 check_parse::<i64>(Mode::Public, 0, 64, 0, 64, &mut rng);
468 check_parse::<i64>(Mode::Private, 0, 0, 64, 64, &mut rng);
469 }
470
471 #[test]
472 fn test_i64_display() {
473 check_display::<i64>();
474 }
475
476 #[test]
479 fn test_u128_new() {
480 let mut rng = TestRng::default();
481
482 check_new::<u128>(Mode::Constant, 128, 0, 0, 0, &mut rng);
483 check_new::<u128>(Mode::Public, 0, 128, 0, 128, &mut rng);
484 check_new::<u128>(Mode::Private, 0, 0, 128, 128, &mut rng);
485 }
486
487 #[test]
488 fn test_u128_parse() {
489 let mut rng = TestRng::default();
490
491 check_parse::<u128>(Mode::Constant, 128, 0, 0, 0, &mut rng);
492 check_parse::<u128>(Mode::Public, 0, 128, 0, 128, &mut rng);
493 check_parse::<u128>(Mode::Private, 0, 0, 128, 128, &mut rng);
494 }
495
496 #[test]
497 fn test_u128_display() {
498 check_display::<u128>();
499 }
500
501 #[test]
504 fn test_i128_new() {
505 let mut rng = TestRng::default();
506
507 check_new::<i128>(Mode::Constant, 128, 0, 0, 0, &mut rng);
508 check_new::<i128>(Mode::Public, 0, 128, 0, 128, &mut rng);
509 check_new::<i128>(Mode::Private, 0, 0, 128, 128, &mut rng);
510 }
511
512 #[test]
513 fn test_i128_parse() {
514 let mut rng = TestRng::default();
515
516 check_parse::<i128>(Mode::Constant, 128, 0, 0, 0, &mut rng);
517 check_parse::<i128>(Mode::Public, 0, 128, 0, 128, &mut rng);
518 check_parse::<i128>(Mode::Private, 0, 0, 128, 128, &mut rng);
519 }
520
521 #[test]
522 fn test_i128_display() {
523 check_display::<i128>();
524 }
525}
526
527#[cfg(test)]
528mod test_utilities {
529 use core::panic::UnwindSafe;
530
531 #[macro_export]
533 macro_rules! test_integer_case {
534 ($test_fn:ident, $primitive:ident, $description:ident) => {
536 paste::paste! {
537 #[test]
538 fn [<test_ $primitive _ $description>]() {
539 $test_fn::<$primitive>();
540 }
541 }
542 };
543 ($test_fn:ident, $primitive:ident, $mode:expr, $description:ident) => {
545 paste::paste! {
546 #[test]
547 fn [<test_ $primitive _ $description>]() {
548 $test_fn::<$primitive>($mode);
549 }
550 }
551 };
552 ($test_fn:ident, $primitive:ident, $mode_a:expr, $mode_b:expr, $description:ident) => {
554 paste::paste! {
555 #[test]
556 fn [<test_ $primitive _ $description>]() {
557 $test_fn::<$primitive>($mode_a, $mode_b);
558 }
559 }
560 };
561 ($test_fn:ident, $primitive_a:ident, $primitive_b:ident, $mode_a:expr, $mode_b:expr, $description:ident) => {
563 paste::paste! {
564 #[test]
565 fn [<test_ $primitive_a _ $description _ $primitive_b>]() {
566 $test_fn::<$primitive_a, $primitive_b>($mode_a, $mode_b);
567 }
568 }
569 };
570 ($test_fn:ident, $primitive:ident, $mode_a:expr, $mode_b:expr, $mode_c:expr, $description:ident) => {
572 paste::paste! {
573 #[test]
574 fn [<test_ $primitive _ $description>]() {
575 $test_fn::<$primitive>($mode_a, $mode_b, $mode_c);
576 }
577 }
578 };
579 (#[$meta:meta], $test_fn:ident, $primitive:ident, $mode:expr, $description:ident) => {
581 paste::paste! {
582 #[test]
583 #[$meta]
584 fn [<test_ $primitive _ $description>]() {
585 $test_fn::<$primitive>($mode);
586 }
587 }
588 };
589 (#[$meta:meta], $test_fn:ident, $primitive:ident, $mode_a:expr, $mode_b:expr, $description:ident) => {
591 paste::paste! {
592 #[test]
593 #[$meta]
594 fn [<test_ $primitive _ $description>]() {
595 $test_fn::<$primitive>($mode_a, $mode_b);
596 }
597 }
598 };
599 (#[$meta:meta], $test_fn:ident, $primitive_a:ident, $primitive_b:ident, $mode_a:expr, $mode_b:expr, $description:ident) => {
601 paste::paste! {
602 #[test]
603 #[$meta]
604 fn [<test_ $primitive_a _ $description _ $primitive_b>]() {
605 $test_fn::<$primitive_a, $primitive_b>($mode_a, $mode_b);
606 }
607 }
608 };
609 (#[$meta:meta], $test_fn:ident, $primitive:ident, $mode_a:expr, $mode_b:expr, $mode_c:expr, $description:ident) => {
611 paste::paste! {
612 #[test]
613 #[$meta]
614 fn [<test_ $primitive _ $description>]() {
615 $test_fn::<$primitive>($mode_a, $mode_b, $mode_c);
616 }
617 }
618 };
619 }
620
621 #[macro_export]
623 macro_rules! test_integer_static {
624 ($test_fn:ident, $primitive:ident, $description:ident) => {
625 test_integer_case!($test_fn, $primitive, $description);
626 };
627 }
628
629 #[macro_export]
631 macro_rules! test_integer_unary {
632 ($test_fn:ident, $primitive:ident, $description:ident) => {
633 paste::paste! {
634 test_integer_case!($test_fn, $primitive, Mode::Constant, [<$description _ constant>]);
635 test_integer_case!($test_fn, $primitive, Mode::Public, [<$description _ public>]);
636 test_integer_case!($test_fn, $primitive, Mode::Private, [<$description _ private>]);
637 }
638 };
639 (#[$meta:meta], $test_fn:ident, $primitive:ident, $description:ident, $variant:ident) => {
640 paste::paste! {
641 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Constant, [<$description _ constant _ $variant>]);
642 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Public, [<$description _ public _ $variant>]);
643 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Private, [<$description _ private _ $variant>]);
644 }
645 };
646 }
647
648 #[macro_export]
650 macro_rules! test_integer_binary {
651 ($test_fn:ident, $primitive:ident, $description:ident) => {
652 paste::paste! {
653 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Constant, [<constant _ $description _ constant>]);
654 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Public, [<constant _ $description _ public>]);
655 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Private, [<constant _ $description _ private>]);
656 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Constant, [<public _ $description _ constant>]);
657 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Public, [<public _ $description _ public>]);
658 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Private, [<public _ $description _ private>]);
659 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Constant, [<private _ $description _ constant>]);
660 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Public, [<private _ $description _ public>]);
661 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Private, [<private _ $description _ private>]);
662 }
663 };
664 ($test_fn:ident, $primitive_a:ident, $primitive_b:ident, $description:ident) => {
665 paste::paste! {
666 test_integer_case!($test_fn, $primitive_a, $primitive_b, Mode::Constant, Mode::Constant, [<constant _ $description _ constant>]);
667 test_integer_case!($test_fn, $primitive_a, $primitive_b, Mode::Constant, Mode::Public, [<constant _ $description _ public>]);
668 test_integer_case!($test_fn, $primitive_a, $primitive_b, Mode::Constant, Mode::Private, [<constant _ $description _ private>]);
669 test_integer_case!($test_fn, $primitive_a, $primitive_b, Mode::Public, Mode::Constant, [<public _ $description _ constant>]);
670 test_integer_case!($test_fn, $primitive_a, $primitive_b, Mode::Public, Mode::Public, [<public _ $description _ public>]);
671 test_integer_case!($test_fn, $primitive_a, $primitive_b, Mode::Public, Mode::Private, [<public _ $description _ private>]);
672 test_integer_case!($test_fn, $primitive_a, $primitive_b, Mode::Private, Mode::Constant, [<private _ $description _ constant>]);
673 test_integer_case!($test_fn, $primitive_a, $primitive_b, Mode::Private, Mode::Public, [<private _ $description _ public>]);
674 test_integer_case!($test_fn, $primitive_a, $primitive_b, Mode::Private, Mode::Private, [<private _ $description _ private>]);
675 }
676 };
677 (#[$meta:meta], $test_fn:ident, $primitive:ident, $description:ident, $variant:ident) => {
678 paste::paste! {
679 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Constant, Mode::Constant, [<constant _ $description _ constant _ $variant>]);
680 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Constant, Mode::Public, [<constant _ $description _ public _ $variant>]);
681 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Constant, Mode::Private, [<constant _ $description _ private _ $variant>]);
682 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Public, Mode::Constant, [<public _ $description _ constant _ $variant>]);
683 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Public, Mode::Public, [<public _ $description _ public _ $variant>]);
684 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Public, Mode::Private, [<public _ $description _ private _ $variant>]);
685 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Private, Mode::Constant, [<private _ $description _ constant _ $variant>]);
686 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Private, Mode::Public, [<private _ $description _ public _ $variant>]);
687 test_integer_case!(#[$meta], $test_fn, $primitive, Mode::Private, Mode::Private, [<private _ $description _ private _ $variant>]);
688 }
689 };
690 (#[$meta:meta], $test_fn:ident, $primitive_a:ident, $primitive_b:ident, $description:ident, $variant:ident) => {
691 paste::paste! {
692 test_integer_case!(#[$meta], $test_fn, $primitive_a, $primitive_b, Mode::Constant, Mode::Constant, [<constant _ $description _ constant _ $variant>]);
693 test_integer_case!(#[$meta], $test_fn, $primitive_a, $primitive_b, Mode::Constant, Mode::Public, [<constant _ $description _ public _ $variant>]);
694 test_integer_case!(#[$meta], $test_fn, $primitive_a, $primitive_b, Mode::Constant, Mode::Private, [<constant _ $description _ private _ $variant>]);
695 test_integer_case!(#[$meta], $test_fn, $primitive_a, $primitive_b, Mode::Public, Mode::Constant, [<public _ $description _ constant _ $variant>]);
696 test_integer_case!(#[$meta], $test_fn, $primitive_a, $primitive_b, Mode::Public, Mode::Public, [<public _ $description _ public _ $variant>]);
697 test_integer_case!(#[$meta], $test_fn, $primitive_a, $primitive_b, Mode::Public, Mode::Private, [<public _ $description _ private _ $variant>]);
698 test_integer_case!(#[$meta], $test_fn, $primitive_a, $primitive_b, Mode::Private, Mode::Constant, [<private _ $description _ constant _ $variant>]);
699 test_integer_case!(#[$meta], $test_fn, $primitive_a, $primitive_b, Mode::Private, Mode::Public, [<private _ $description _ public _ $variant>]);
700 test_integer_case!(#[$meta], $test_fn, $primitive_a, $primitive_b, Mode::Private, Mode::Private, [<private _ $description _ private _ $variant>]);
701 }
702 };
703 }
704
705 #[macro_export]
707 macro_rules! test_integer_ternary {
708 ($test_fn:ident, $primitive:ident, $description_a:ident, $description_b:ident, $description_c:ident) => {
709 paste::paste! {
710 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Constant, Mode::Constant, [<$description_a _ constant _ $description_b _ constant _ $description_c _ constant>]);
711 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Constant, Mode::Public, [<$description_a _ constant _ $description_b _ constant _ $description_c _ public>]);
712 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Constant, Mode::Private, [<$description_a _ constant _ $description_b _ constant _ $description_c _ private>]);
713 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Public, Mode::Constant, [<$description_a _ constant _ $description_b _ public _ $description_c _ constant>]);
714 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Public, Mode::Public, [<$description_a _ constant _ $description_b _ public _ $description_c _ public>]);
715 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Public, Mode::Private, [<$description_a _ constant _ $description_b _ public _ $description_c _ private>]);
716 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Private, Mode::Constant, [<$description_a _ constant _ $description_b _ private _ $description_c _ constant>]);
717 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Private, Mode::Public, [<$description_a _ constant _ $description_b _ private _ $description_c _ public>]);
718 test_integer_case!($test_fn, $primitive, Mode::Constant, Mode::Private, Mode::Private, [<$description_a _ constant _ $description_b _ private _ $description_c _ private>]);
719 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Constant, Mode::Constant, [<$description_a _ public _ $description_b _ constant _ $description_c _ constant>]);
720 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Constant, Mode::Public, [<$description_a _ public _ $description_b _ constant _ $description_c _ public>]);
721 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Constant, Mode::Private, [<$description_a _ public _ $description_b _ constant _ $description_c _ private>]);
722 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Public, Mode::Constant, [<$description_a _ public _ $description_b _ public _ $description_c _ constant>]);
723 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Public, Mode::Public, [<$description_a _ public _ $description_b _ public _ $description_c _ public>]);
724 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Public, Mode::Private, [<$description_a _ public _ $description_b _ public _ $description_c _ private>]);
725 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Private, Mode::Constant, [<$description_a _ public _ $description_b _ private _ $description_c _ constant>]);
726 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Private, Mode::Public, [<$description_a _ public _ $description_b _ private _ $description_c _ public>]);
727 test_integer_case!($test_fn, $primitive, Mode::Public, Mode::Private, Mode::Private, [<$description_a _ public _ $description_b _ private _ $description_c _ private>]);
728 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Constant, Mode::Constant, [<$description_a _ private _ $description_b _ constant _ $description_c _ constant>]);
729 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Constant, Mode::Public, [<$description_a _ private _ $description_b _ constant _ $description_c _ public>]);
730 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Constant, Mode::Private, [<$description_a _ private _ $description_b _ constant _ $description_c _ private>]);
731 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Public, Mode::Constant, [<$description_a _ private _ $description_b _ public _ $description_c _ constant>]);
732 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Public, Mode::Public, [<$description_a _ private _ $description_b _ public _ $description_c _ public>]);
733 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Public, Mode::Private, [<$description_a _ private _ $description_b _ public _ $description_c _ private>]);
734 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Private, Mode::Constant, [<$description_a _ private _ $description_b _ private _ $description_c _ constant>]);
735 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Private, Mode::Public, [<$description_a _ private _ $description_b _ private _ $description_c _ public>]);
736 test_integer_case!($test_fn, $primitive, Mode::Private, Mode::Private, Mode::Private, [<$description_a _ private _ $description_b _ private _ $description_c _ private>]);
737 }
738 };
739 }
740
741 pub fn check_operation_halts<LHS: UnwindSafe, RHS: UnwindSafe, OUT>(
742 a: LHS,
743 b: RHS,
744 operation: impl FnOnce(LHS, RHS) -> OUT + UnwindSafe,
745 ) {
746 let result = std::panic::catch_unwind(|| operation(a, b));
747 assert!(result.is_err());
748 }
749
750 pub fn check_unary_operation_halts<IN: UnwindSafe, OUT>(input: IN, operation: impl FnOnce(IN) -> OUT + UnwindSafe) {
751 let result = std::panic::catch_unwind(|| operation(input));
752 assert!(result.is_err());
753 }
754}