Skip to main content

crypto_bigint/
non_zero.rs

1//! Wrapper type for non-zero integers.
2
3use crate::{
4    Bounded, Choice, ConstOne, Constants, CtAssign, CtEq, CtOption, CtSelect, Encoding, Int, Limb,
5    Mul, Odd, One, ToUnsigned, Uint, UintRef, Zero,
6};
7use core::{
8    fmt,
9    num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128},
10    ops::Deref,
11};
12use ctutils::{CtAssignSlice, CtEqSlice};
13
14#[cfg(feature = "alloc")]
15use crate::BoxedUint;
16
17#[cfg(feature = "hybrid-array")]
18use crate::{ArrayEncoding, ByteArray};
19
20#[cfg(feature = "rand_core")]
21use {crate::Random, rand_core::TryRng};
22
23#[cfg(feature = "serde")]
24use serdect::serde::{
25    Deserialize, Deserializer, Serialize, Serializer,
26    de::{Error, Unexpected},
27};
28
29/// Non-zero limb.
30pub type NonZeroLimb = NonZero<Limb>;
31
32/// Non-zero unsigned integer.
33pub type NonZeroUint<const LIMBS: usize> = NonZero<Uint<LIMBS>>;
34
35/// Non-zero unsigned integer reference.
36pub type NonZeroUintRef = NonZero<UintRef>;
37
38/// Non-zero signed integer.
39pub type NonZeroInt<const LIMBS: usize> = NonZero<Int<LIMBS>>;
40
41/// Non-zero boxed unsigned integer.
42#[cfg(feature = "alloc")]
43pub type NonZeroBoxedUint = NonZero<BoxedUint>;
44
45/// Wrapper type for non-zero integers.
46#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
47#[repr(transparent)]
48pub struct NonZero<T: ?Sized>(pub(crate) T);
49
50impl<T> NonZero<T> {
51    /// Create a new non-zero integer.
52    #[inline]
53    pub fn new(mut n: T) -> CtOption<Self>
54    where
55        T: Zero + One + CtAssign,
56    {
57        let is_zero = n.is_zero();
58
59        // Use one as a placeholder in the event zero is provided, so functions that operate on
60        // `NonZero` values really can expect the value to never be zero, even in the case
61        // `CtOption::is_some` is false.
62        n.ct_assign(&T::one_like(&n), is_zero);
63        CtOption::new(Self(n), !is_zero)
64    }
65
66    /// Returns the inner value.
67    #[inline]
68    pub fn get(self) -> T {
69        self.0
70    }
71
72    /// Returns a copy of the inner value for `Copy` types.
73    ///
74    /// This allows the function to be `const fn`, since `Copy` is implicitly `!Drop`, which avoids
75    /// problems around `const fn` destructors.
76    #[inline]
77    pub const fn get_copy(self) -> T
78    where
79        T: Copy,
80    {
81        self.0
82    }
83}
84
85impl<T: ?Sized> NonZero<T> {
86    /// Provides access to the contents of `NonZero` in a `const` context.
87    pub const fn as_ref(&self) -> &T {
88        &self.0
89    }
90}
91
92impl<T> NonZero<T>
93where
94    T: Bounded + ?Sized,
95{
96    /// Total size of the represented integer in bits.
97    pub const BITS: u32 = T::BITS;
98
99    /// Total size of the represented integer in bytes.
100    pub const BYTES: usize = T::BYTES;
101}
102
103impl<T> NonZero<T>
104where
105    T: Constants,
106{
107    /// The value `1`.
108    pub const ONE: Self = Self(T::ONE);
109
110    /// Maximum value this integer can express.
111    pub const MAX: Self = Self(T::MAX);
112}
113
114impl<T> NonZero<T>
115where
116    T: Zero + One + CtAssign + Encoding,
117{
118    /// Decode from big endian bytes.
119    pub fn from_be_bytes(bytes: T::Repr) -> CtOption<Self> {
120        Self::new(T::from_be_bytes(bytes))
121    }
122
123    /// Decode from little endian bytes.
124    pub fn from_le_bytes(bytes: T::Repr) -> CtOption<Self> {
125        Self::new(T::from_le_bytes(bytes))
126    }
127}
128
129impl<T> ConstOne for NonZero<T>
130where
131    T: ConstOne + One,
132{
133    const ONE: Self = Self(T::ONE);
134}
135
136impl<T> One for NonZero<T>
137where
138    T: One,
139    Self: CtEq,
140{
141    #[inline]
142    fn one() -> Self {
143        Self(T::one())
144    }
145}
146
147impl<T> num_traits::One for NonZero<T>
148where
149    T: One + Mul<T, Output = T>,
150{
151    #[inline]
152    fn one() -> Self {
153        Self(T::one())
154    }
155
156    fn is_one(&self) -> bool {
157        self.0.is_one().into()
158    }
159}
160
161/// Any non-zero integer multiplied by another non-zero integer is definitionally non-zero.
162impl<T> Mul<Self> for NonZero<T>
163where
164    T: Mul<T, Output = T>,
165{
166    type Output = Self;
167
168    fn mul(self, rhs: Self) -> Self {
169        Self(self.0 * rhs.0)
170    }
171}
172
173impl NonZero<Limb> {
174    /// Creates a new non-zero limb in a const context.
175    ///
176    /// # Panics
177    /// - if the value is zero.
178    ///
179    /// # Note
180    /// In future versions of Rust it should be possible to replace this with
181    /// `NonZero::new(…).unwrap()`
182    // TODO: Remove when `Self::new` and `CtOption::unwrap` support `const fn`
183    #[inline]
184    #[must_use]
185    #[track_caller]
186    pub const fn new_unwrap(n: Limb) -> Self {
187        assert!(n.is_nonzero().to_bool_vartime(), "invalid value: zero");
188        Self(n)
189    }
190
191    /// Create a [`NonZero<Limb>`] from a [`NonZeroU8`] (const-friendly)
192    // TODO(tarcieri): replace with `const impl From<NonZeroU8>` when stable
193    #[must_use]
194    pub const fn from_u8(n: NonZeroU8) -> Self {
195        Self(Limb::from_u8(n.get()))
196    }
197
198    /// Create a [`NonZero<Limb>`] from a [`NonZeroU16`] (const-friendly)
199    // TODO(tarcieri): replace with `const impl From<NonZeroU16>` when stable
200    #[must_use]
201    pub const fn from_u16(n: NonZeroU16) -> Self {
202        Self(Limb::from_u16(n.get()))
203    }
204
205    /// Create a [`NonZero<Limb>`] from a [`NonZeroU32`] (const-friendly)
206    // TODO(tarcieri): replace with `const impl From<NonZeroU32>` when stable
207    #[must_use]
208    pub const fn from_u32(n: NonZeroU32) -> Self {
209        Self(Limb::from_u32(n.get()))
210    }
211
212    cpubits::cpubits! {
213        64 => {
214            /// Create a [`NonZero<Limb>`] from a [`NonZeroU64`] (const-friendly)
215            // TODO(tarcieri): replace with `const impl From<NonZeroU64>` when stable
216            #[must_use]
217            pub const fn from_u64(n: NonZeroU64) -> Self {
218                Self(Limb::from_u64(n.get()))
219            }
220        }
221    }
222}
223
224impl<const LIMBS: usize> NonZeroUint<LIMBS> {
225    /// Creates a new non-zero integer in a const context.
226    ///
227    /// In future versions of Rust it should be possible to replace this with
228    /// `NonZero::new(…).unwrap()`
229    ///
230    /// # Panics
231    /// - if the value is zero.
232    // TODO: Remove when `Self::new` and `CtOption::unwrap` support `const fn`
233    #[inline]
234    #[track_caller]
235    #[must_use]
236    pub const fn new_unwrap(n: Uint<LIMBS>) -> Self {
237        assert!(n.is_nonzero().to_bool_vartime(), "invalid value: zero");
238        Self(n)
239    }
240
241    /// Create a new [`NonZero<Uint>`] from the provided big endian hex string.
242    ///
243    /// # Panics
244    /// - if the hex is zero, malformed, or not zero-padded accordingly for the size.
245    #[track_caller]
246    #[must_use]
247    pub const fn from_be_hex(hex: &str) -> Self {
248        Self::new_unwrap(Uint::from_be_hex(hex))
249    }
250
251    /// Create a new [`NonZero<Uint>`] from the provided little endian hex string.
252    ///
253    /// # Panics
254    /// - if the hex is zero, malformed, or not zero-padded accordingly for the size.
255    #[track_caller]
256    #[must_use]
257    pub const fn from_le_hex(hex: &str) -> Self {
258        Self::new_unwrap(Uint::from_le_hex(hex))
259    }
260
261    /// Create a [`NonZeroUint`] from a [`NonZeroU8`] (const-friendly)
262    // TODO(tarcieri): replace with `const impl From<NonZeroU8>` when stable
263    #[must_use]
264    pub const fn from_u8(n: NonZeroU8) -> Self {
265        Self(Uint::from_u8(n.get()))
266    }
267
268    /// Create a [`NonZeroUint`] from a [`NonZeroU16`] (const-friendly)
269    // TODO(tarcieri): replace with `const impl From<NonZeroU16>` when stable
270    #[must_use]
271    pub const fn from_u16(n: NonZeroU16) -> Self {
272        Self(Uint::from_u16(n.get()))
273    }
274
275    /// Create a [`NonZeroUint`] from a [`NonZeroU32`] (const-friendly)
276    // TODO(tarcieri): replace with `const impl From<NonZeroU32>` when stable
277    #[must_use]
278    pub const fn from_u32(n: NonZeroU32) -> Self {
279        Self(Uint::from_u32(n.get()))
280    }
281
282    /// Create a [`NonZeroUint`] from a [`NonZeroU64`] (const-friendly)
283    // TODO(tarcieri): replace with `const impl From<NonZeroU64>` when stable
284    #[must_use]
285    pub const fn from_u64(n: NonZeroU64) -> Self {
286        Self(Uint::from_u64(n.get()))
287    }
288
289    /// Create a [`NonZeroUint`] from a [`NonZeroU128`] (const-friendly)
290    // TODO(tarcieri): replace with `const impl From<NonZeroU128>` when stable
291    #[must_use]
292    pub const fn from_u128(n: NonZeroU128) -> Self {
293        Self(Uint::from_u128(n.get()))
294    }
295
296    /// Borrow this `NonZero<Uint>` as a `&NonZeroUintRef`.
297    #[inline]
298    #[must_use]
299    pub const fn as_uint_ref(&self) -> &NonZeroUintRef {
300        self.0.as_uint_ref().as_nz_unchecked()
301    }
302}
303
304impl<const LIMBS: usize> AsRef<NonZeroUintRef> for NonZeroUint<LIMBS> {
305    fn as_ref(&self) -> &NonZeroUintRef {
306        self.as_uint_ref()
307    }
308}
309
310impl<const LIMBS: usize> NonZeroInt<LIMBS> {
311    /// Creates a new non-zero integer in a const context.
312    ///
313    /// # Panics
314    /// - if the value is zero.
315    ///
316    /// # Note
317    /// In future versions of Rust it should be possible to replace this with
318    /// `NonZero::new(…).unwrap()`
319    // TODO: Remove when `Self::new` and `CtOption::unwrap` support `const fn`
320    #[inline]
321    #[must_use]
322    #[track_caller]
323    pub const fn new_unwrap(n: Int<LIMBS>) -> Self {
324        assert!(n.is_nonzero().to_bool_vartime(), "invalid value: zero");
325        Self(n)
326    }
327
328    /// The sign and magnitude of this [`NonZeroInt`].
329    #[must_use]
330    pub const fn abs_sign(&self) -> (NonZero<Uint<LIMBS>>, Choice) {
331        let (abs, sign) = self.0.abs_sign();
332        // Absolute value of a non-zero value is non-zero
333        (NonZero(abs), sign)
334    }
335
336    /// The magnitude of this [`NonZeroInt`].
337    #[must_use]
338    pub const fn abs(&self) -> NonZero<Uint<LIMBS>> {
339        self.abs_sign().0
340    }
341}
342
343#[cfg(feature = "alloc")]
344impl NonZeroBoxedUint {
345    /// Borrow this `NonZeroBoxedUint` as a `&NonZeroUintRef`.
346    #[inline]
347    #[must_use]
348    pub fn as_uint_ref(&self) -> &NonZeroUintRef {
349        self.0.as_uint_ref().as_nz_unchecked()
350    }
351}
352
353#[cfg(feature = "alloc")]
354impl AsRef<NonZeroUintRef> for NonZeroBoxedUint {
355    fn as_ref(&self) -> &NonZeroUintRef {
356        self.as_uint_ref()
357    }
358}
359
360#[cfg(feature = "alloc")]
361impl<T: AsRef<UintRef> + ?Sized> NonZero<T> {
362    /// Get the least significant limb as a [`NonZeroLimb`].
363    pub(crate) fn lower_limb(&self) -> NonZeroLimb {
364        NonZero(self.0.as_ref().limbs[0])
365    }
366
367    /// Convert to a [`NonZeroBoxedUint`].
368    pub(crate) fn to_boxed(&self) -> NonZeroBoxedUint {
369        NonZero(BoxedUint::from(self.0.as_ref()))
370    }
371}
372
373impl<T: ToUnsigned + ?Sized> NonZero<T> {
374    /// Convert from a reference into an owned `NonZero<T: Unsigned>`.
375    pub fn to_unsigned(&self) -> NonZero<T::Unsigned> {
376        NonZero(self.0.to_unsigned())
377    }
378}
379
380#[cfg(feature = "hybrid-array")]
381impl<T> NonZero<T>
382where
383    T: ArrayEncoding + Zero + One + CtAssign,
384{
385    /// Decode a non-zero integer from big endian bytes.
386    pub fn from_be_byte_array(bytes: ByteArray<T>) -> CtOption<Self> {
387        Self::new(T::from_be_byte_array(bytes))
388    }
389
390    /// Decode a non-zero integer from little endian bytes.
391    pub fn from_le_byte_array(bytes: ByteArray<T>) -> CtOption<Self> {
392        Self::new(T::from_le_byte_array(bytes))
393    }
394}
395
396impl<T: ?Sized> AsRef<T> for NonZero<T> {
397    fn as_ref(&self) -> &T {
398        &self.0
399    }
400}
401
402impl<T> CtAssign for NonZero<T>
403where
404    T: CtAssign,
405{
406    #[inline]
407    fn ct_assign(&mut self, other: &Self, choice: Choice) {
408        self.0.ct_assign(&other.0, choice);
409    }
410}
411impl<T> CtAssignSlice for NonZero<T> where T: CtAssign {}
412
413impl<T> CtEq for NonZero<T>
414where
415    T: CtEq + ?Sized,
416{
417    #[inline]
418    fn ct_eq(&self, other: &Self) -> Choice {
419        CtEq::ct_eq(&self.0, &other.0)
420    }
421}
422impl<T> CtEqSlice for NonZero<T> where T: CtEq {}
423
424impl<T> CtSelect for NonZero<T>
425where
426    T: CtSelect,
427{
428    #[inline]
429    fn ct_select(&self, other: &Self, choice: Choice) -> Self {
430        Self(self.0.ct_select(&other.0, choice))
431    }
432}
433
434impl<T> Default for NonZero<T>
435where
436    T: One,
437{
438    #[inline]
439    fn default() -> Self {
440        Self(T::one())
441    }
442}
443
444impl<T: ?Sized> Deref for NonZero<T> {
445    type Target = T;
446
447    fn deref(&self) -> &T {
448        &self.0
449    }
450}
451
452#[cfg(feature = "rand_core")]
453impl<T> Random for NonZero<T>
454where
455    T: Random + Zero + One + CtAssign,
456{
457    /// This uses rejection sampling to avoid zero.
458    ///
459    /// As a result, it runs in variable time. If the generator `rng` is
460    /// cryptographically secure (for example, it implements `CryptoRng`),
461    /// then this is guaranteed not to leak anything about the output value.
462    fn try_random_from_rng<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
463        loop {
464            if let Some(result) = Self::new(T::try_random_from_rng(rng)?).into() {
465                break Ok(result);
466            }
467        }
468    }
469}
470
471impl From<NonZeroU8> for NonZero<Limb> {
472    fn from(integer: NonZeroU8) -> Self {
473        Self::from_u8(integer)
474    }
475}
476
477impl From<NonZeroU16> for NonZero<Limb> {
478    fn from(integer: NonZeroU16) -> Self {
479        Self::from_u16(integer)
480    }
481}
482
483impl From<NonZeroU32> for NonZero<Limb> {
484    fn from(integer: NonZeroU32) -> Self {
485        Self::from_u32(integer)
486    }
487}
488
489cpubits::cpubits! {
490    64 => {
491        impl From<NonZeroU64> for NonZero<Limb> {
492            fn from(integer: NonZeroU64) -> Self {
493                Self::from_u64(integer)
494            }
495        }
496    }
497}
498
499impl<const LIMBS: usize> From<NonZeroU8> for NonZero<Uint<LIMBS>> {
500    fn from(integer: NonZeroU8) -> Self {
501        Self::from_u8(integer)
502    }
503}
504
505impl<const LIMBS: usize> From<NonZeroU16> for NonZero<Uint<LIMBS>> {
506    fn from(integer: NonZeroU16) -> Self {
507        Self::from_u16(integer)
508    }
509}
510
511impl<const LIMBS: usize> From<NonZeroU32> for NonZero<Uint<LIMBS>> {
512    fn from(integer: NonZeroU32) -> Self {
513        Self::from_u32(integer)
514    }
515}
516
517impl<const LIMBS: usize> From<NonZeroU64> for NonZero<Uint<LIMBS>> {
518    fn from(integer: NonZeroU64) -> Self {
519        Self::from_u64(integer)
520    }
521}
522
523impl<const LIMBS: usize> From<NonZeroU128> for NonZero<Uint<LIMBS>> {
524    fn from(integer: NonZeroU128) -> Self {
525        Self::from_u128(integer)
526    }
527}
528
529impl<T> From<Odd<T>> for NonZero<T> {
530    fn from(odd: Odd<T>) -> NonZero<T> {
531        NonZero(odd.get())
532    }
533}
534
535impl<T> fmt::Display for NonZero<T>
536where
537    T: fmt::Display + ?Sized,
538{
539    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
540        fmt::Display::fmt(&self.0, f)
541    }
542}
543
544impl<T> fmt::Binary for NonZero<T>
545where
546    T: fmt::Binary + ?Sized,
547{
548    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549        fmt::Binary::fmt(&self.0, f)
550    }
551}
552
553impl<T> fmt::Octal for NonZero<T>
554where
555    T: fmt::Octal + ?Sized,
556{
557    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
558        fmt::Octal::fmt(&self.0, f)
559    }
560}
561
562impl<T> fmt::LowerHex for NonZero<T>
563where
564    T: fmt::LowerHex + ?Sized,
565{
566    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
567        fmt::LowerHex::fmt(&self.0, f)
568    }
569}
570
571impl<T> fmt::UpperHex for NonZero<T>
572where
573    T: fmt::UpperHex + ?Sized,
574{
575    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
576        fmt::UpperHex::fmt(&self.0, f)
577    }
578}
579
580#[cfg(feature = "serde")]
581impl<'de, T: Deserialize<'de> + Zero> Deserialize<'de> for NonZero<T> {
582    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
583    where
584        D: Deserializer<'de>,
585    {
586        let value: T = T::deserialize(deserializer)?;
587
588        if bool::from(value.is_zero()) {
589            Err(D::Error::invalid_value(
590                Unexpected::Other("zero"),
591                &"a non-zero value",
592            ))
593        } else {
594            Ok(Self(value))
595        }
596    }
597}
598
599#[cfg(feature = "serde")]
600impl<T: Serialize + Zero> Serialize for NonZero<T> {
601    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
602    where
603        S: Serializer,
604    {
605        self.0.serialize(serializer)
606    }
607}
608
609#[cfg(feature = "subtle")]
610impl<T> subtle::ConditionallySelectable for NonZero<T>
611where
612    T: Copy,
613    Self: CtSelect,
614{
615    fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
616        CtSelect::ct_select(a, b, choice.into())
617    }
618}
619
620#[cfg(feature = "subtle")]
621impl<T> subtle::ConstantTimeEq for NonZero<T>
622where
623    T: ?Sized,
624    Self: CtEq,
625{
626    #[inline]
627    fn ct_eq(&self, other: &Self) -> subtle::Choice {
628        CtEq::ct_eq(self, other).into()
629    }
630}
631
632#[cfg(feature = "zeroize")]
633impl<T: zeroize::Zeroize + Zero> zeroize::Zeroize for NonZero<T> {
634    fn zeroize(&mut self) {
635        self.0.zeroize();
636    }
637}
638
639#[cfg(test)]
640mod tests {
641    use super::NonZero;
642    use crate::{I128, One, U128};
643    use hex_literal::hex;
644
645    #[test]
646    fn default() {
647        assert!(!NonZero::<U128>::default().is_zero().to_bool());
648    }
649
650    #[test]
651    fn from_be_bytes() {
652        assert_eq!(
653            NonZero::<U128>::from_be_bytes(hex!("00000000000000000000000000000001").into())
654                .unwrap(),
655            NonZero::<U128>::ONE
656        );
657
658        assert_eq!(
659            NonZero::<U128>::from_be_bytes(hex!("00000000000000000000000000000000").into())
660                .into_option(),
661            None
662        );
663    }
664
665    #[test]
666    fn from_le_bytes() {
667        assert_eq!(
668            NonZero::<U128>::from_le_bytes(hex!("01000000000000000000000000000000").into())
669                .unwrap(),
670            NonZero::<U128>::ONE
671        );
672
673        assert_eq!(
674            NonZero::<U128>::from_le_bytes(hex!("00000000000000000000000000000000").into())
675                .into_option(),
676            None
677        );
678    }
679
680    #[test]
681    fn from_be_hex_when_nonzero() {
682        assert_eq!(
683            NonZero::<U128>::from_be_hex("00000000000000000000000000000001"),
684            NonZero::<U128>::ONE
685        );
686    }
687
688    #[test]
689    #[should_panic]
690    fn from_be_hex_when_zero() {
691        let _ = NonZero::<U128>::from_be_hex("00000000000000000000000000000000");
692    }
693
694    #[test]
695    fn from_le_hex_when_nonzero() {
696        assert_eq!(
697            NonZero::<U128>::from_le_hex("01000000000000000000000000000000"),
698            NonZero::<U128>::ONE
699        );
700    }
701
702    #[test]
703    #[should_panic]
704    fn from_le_hex_when_zero() {
705        let _ = NonZero::<U128>::from_le_hex("00000000000000000000000000000000");
706    }
707
708    #[test]
709    fn int_abs_sign() {
710        let x = I128::from(-55).to_nz().unwrap();
711        let (abs, sgn) = x.abs_sign();
712        assert_eq!(abs, U128::from(55u32).to_nz().unwrap());
713        assert!(sgn.to_bool());
714    }
715
716    #[test]
717    fn one() {
718        assert_eq!(
719            NonZero::<U128>::from_le_bytes(hex!("01000000000000000000000000000000").into())
720                .unwrap(),
721            NonZero::<U128>::one()
722        );
723    }
724
725    #[cfg(feature = "hybrid-array")]
726    #[test]
727    fn from_le_byte_array() {
728        assert_eq!(
729            NonZero::<U128>::from_le_byte_array(hex!("01000000000000000000000000000000").into())
730                .unwrap(),
731            NonZero::<U128>::ONE
732        );
733    }
734}