1use crate::Choice;
2use core::{
3 cmp,
4 num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize},
5};
6
7pub trait CtGt {
9 #[must_use]
11 fn ct_gt(&self, other: &Self) -> Choice;
12}
13
14macro_rules! impl_unsigned_ct_gt {
16 ( $($uint:ty),+ ) => {
17 $(
18 impl CtGt for $uint {
19 #[inline]
20 fn ct_gt(&self, other: &Self) -> Choice {
21 let (_, overflow) = other.overflowing_sub(*self);
22 Choice(overflow.into())
23 }
24 }
25 )+
26 };
27}
28
29impl_unsigned_ct_gt!(u8, u16, u32, u64, u128, usize);
30
31macro_rules! impl_ct_gt_for_nonzero_integer {
33 ( $($ty:ty),+ ) => {
34 $(
35 impl CtGt for $ty {
36 #[inline]
37 fn ct_gt(&self, other: &Self) -> Choice {
38 self.get().ct_gt(&other.get())
39 }
40 }
41 )+
42 };
43}
44
45impl_ct_gt_for_nonzero_integer!(
46 NonZeroU8,
47 NonZeroU16,
48 NonZeroU32,
49 NonZeroU64,
50 NonZeroU128,
51 NonZeroUsize
52);
53
54impl CtGt for cmp::Ordering {
55 #[inline]
56 #[allow(clippy::arithmetic_side_effects, clippy::cast_sign_loss)]
57 fn ct_gt(&self, other: &Self) -> Choice {
58 let a = (*self as i8) + 1;
61 let b = (*other as i8) + 1;
62
63 (a as u8).ct_gt(&(b as u8))
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::CtGt;
71 use core::cmp::Ordering;
72
73 macro_rules! ct_gt_tests {
75 ( $($int:ident),+ ) => {
76 $(
77 mod $int {
78 use super::CtGt;
79
80 #[test]
81 fn ct_gt() {
82 let a = <$int>::MIN;
83 let b = <$int>::MAX;
84 assert!(!a.ct_gt(&a).to_bool());
85 assert!(!a.ct_gt(&b).to_bool());
86 assert!(b.ct_gt(&a).to_bool());
87 }
88
89 }
90 )+
91 };
92 }
93
94 ct_gt_tests!(u8, u16, u32, u64, u128, usize);
95
96 #[test]
97 fn ordering() {
98 assert!(!Ordering::Equal.ct_gt(&Ordering::Equal).to_bool());
99 assert!(!Ordering::Less.ct_gt(&Ordering::Greater).to_bool());
100 assert!(Ordering::Greater.ct_gt(&Ordering::Less).to_bool());
101 }
102}