|
1 | 1 | use crate::{Choice, CtAssign, CtSelect}; |
| 2 | +use core::num::{ |
| 3 | + NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroU8, NonZeroU16, NonZeroU32, |
| 4 | + NonZeroU64, NonZeroU128, |
| 5 | +}; |
2 | 6 |
|
3 | 7 | /// Constant-time conditional negation: negates a value when `choice` is [`Choice::TRUE`]. |
4 | 8 | pub trait CtNeg: Sized { |
@@ -58,6 +62,42 @@ macro_rules! impl_unsigned_ct_neg { |
58 | 62 | impl_signed_ct_neg!(i8, i16, i32, i64, i128); |
59 | 63 | impl_unsigned_ct_neg!(u8, u16, u32, u64, u128); |
60 | 64 |
|
| 65 | +/// Impl `CtNeg` for `NonZero<T>` by calling the `CtNeg` impl for `T`. |
| 66 | +macro_rules! impl_ct_neg_for_nonzero_integer { |
| 67 | + ( $($nzint:ident),+ ) => { |
| 68 | + $( |
| 69 | + impl CtNeg for $nzint { |
| 70 | + #[inline] |
| 71 | + fn ct_neg(&self, choice: Choice) -> Self { |
| 72 | + let n = self.get().ct_neg(choice); |
| 73 | + |
| 74 | + // SAFETY: we are constructing `NonZero` from a value we obtained from |
| 75 | + // `NonZero::get`, which ensures it's non-zero, and the negation of a non-zero |
| 76 | + // integer will always be non-zero: |
| 77 | + // |
| 78 | + // - signed: `{i*}::MIN` and `{i*}::MAX` are each other's negations |
| 79 | + // - unsigned: `1` and `{u*}::MAX` are each other's negations |
| 80 | + #[allow(unsafe_code)] |
| 81 | + unsafe { $nzint::new_unchecked(n) } |
| 82 | + } |
| 83 | + } |
| 84 | + )+ |
| 85 | + }; |
| 86 | +} |
| 87 | + |
| 88 | +impl_ct_neg_for_nonzero_integer!( |
| 89 | + NonZeroI8, |
| 90 | + NonZeroI16, |
| 91 | + NonZeroI32, |
| 92 | + NonZeroI64, |
| 93 | + NonZeroI128, |
| 94 | + NonZeroU8, |
| 95 | + NonZeroU16, |
| 96 | + NonZeroU32, |
| 97 | + NonZeroU64, |
| 98 | + NonZeroU128 |
| 99 | +); |
| 100 | + |
61 | 101 | #[cfg(test)] |
62 | 102 | mod tests { |
63 | 103 | /// Test `CtNeg` impl on `i*` |
|
0 commit comments