crypto_bigint/
limb.rs

1//! Big integers are represented as an array of smaller CPU word-size integers
2//! called "limbs".
3
4#![allow(clippy::derive_hash_xor_eq)]
5
6mod add;
7mod bit_and;
8mod bit_not;
9mod bit_or;
10mod bit_xor;
11mod bits;
12mod cmp;
13mod encoding;
14mod from;
15mod mul;
16mod shl;
17mod shr;
18mod sub;
19
20#[cfg(feature = "rand_core")]
21mod rand;
22
23use crate::Zero;
24use core::fmt;
25use subtle::{Choice, ConditionallySelectable};
26
27#[cfg(feature = "serde")]
28use serdect::serde::{Deserialize, Deserializer, Serialize, Serializer};
29
30#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
31compile_error!("this crate builds on 32-bit and 64-bit platforms only");
32
33//
34// 32-bit definitions
35//
36
37/// Inner integer type that the [`Limb`] newtype wraps.
38#[cfg(target_pointer_width = "32")]
39pub type Word = u32;
40
41/// Signed integer type that corresponds to [`Word`].
42#[cfg(target_pointer_width = "32")]
43pub(crate) type SignedWord = i32;
44
45/// Unsigned wide integer type: double the width of [`Word`].
46#[cfg(target_pointer_width = "32")]
47pub type WideWord = u64;
48
49/// Signed wide integer type: double the width of [`Limb`].
50#[cfg(target_pointer_width = "32")]
51pub(crate) type WideSignedWord = i64;
52
53//
54// 64-bit definitions
55//
56
57/// Unsigned integer type that the [`Limb`] newtype wraps.
58#[cfg(target_pointer_width = "64")]
59pub type Word = u64;
60
61/// Signed integer type that corresponds to [`Word`].
62#[cfg(target_pointer_width = "64")]
63pub(crate) type SignedWord = i64;
64
65/// Wide integer type: double the width of [`Word`].
66#[cfg(target_pointer_width = "64")]
67pub type WideWord = u128;
68
69/// Signed wide integer type: double the width of [`SignedWord`].
70#[cfg(target_pointer_width = "64")]
71pub(crate) type WideSignedWord = i128;
72
73//
74// Deprecated legacy names
75//
76
77// TODO(tarcieri): remove these in the next breaking release
78
79/// Deprecated: unsigned integer type that the [`Limb`] newtype wraps.
80#[deprecated(since = "0.4.8", note = "please use `Word` instead")]
81pub type LimbUInt = Word;
82
83/// Deprecated: wide integer type which is double the width of [`Word`].
84#[deprecated(since = "0.4.8", note = "please use `WideWord` instead")]
85pub type WideLimbUInt = WideWord;
86
87/// Highest bit in a [`Limb`].
88pub(crate) const HI_BIT: usize = Limb::BIT_SIZE - 1;
89
90/// Big integers are represented as an array of smaller CPU word-size integers
91/// called "limbs".
92#[derive(Copy, Clone, Debug, Default, Hash)]
93#[repr(transparent)]
94pub struct Limb(pub Word);
95
96impl Limb {
97    /// The value `0`.
98    pub const ZERO: Self = Limb(0);
99
100    /// The value `1`.
101    pub const ONE: Self = Limb(1);
102
103    /// Maximum value this [`Limb`] can express.
104    pub const MAX: Self = Limb(Word::MAX);
105
106    // 32-bit
107
108    /// Size of the inner integer in bits.
109    #[cfg(target_pointer_width = "32")]
110    pub const BIT_SIZE: usize = 32;
111    /// Size of the inner integer in bytes.
112    #[cfg(target_pointer_width = "32")]
113    pub const BYTE_SIZE: usize = 4;
114
115    // 64-bit
116
117    /// Size of the inner integer in bits.
118    #[cfg(target_pointer_width = "64")]
119    pub const BIT_SIZE: usize = 64;
120    /// Size of the inner integer in bytes.
121    #[cfg(target_pointer_width = "64")]
122    pub const BYTE_SIZE: usize = 8;
123
124    /// Return `a` if `c`==0 or `b` if `c`==`Word::MAX`.
125    ///
126    /// Const-friendly: we can't yet use `subtle` in `const fn` contexts.
127    #[inline]
128    pub(crate) const fn ct_select(a: Self, b: Self, c: Word) -> Self {
129        Self(a.0 ^ (c & (a.0 ^ b.0)))
130    }
131}
132
133impl ConditionallySelectable for Limb {
134    #[inline]
135    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
136        Self(Word::conditional_select(&a.0, &b.0, choice))
137    }
138}
139
140impl Zero for Limb {
141    const ZERO: Self = Self::ZERO;
142}
143
144impl fmt::Display for Limb {
145    #[inline]
146    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147        fmt::UpperHex::fmt(self, f)
148    }
149}
150
151impl fmt::LowerHex for Limb {
152    #[inline]
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        write!(f, "{:0width$x}", &self.0, width = Self::BYTE_SIZE * 2)
155    }
156}
157
158impl fmt::UpperHex for Limb {
159    #[inline]
160    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161        write!(f, "{:0width$X}", &self.0, width = Self::BYTE_SIZE * 2)
162    }
163}
164
165#[cfg(feature = "serde")]
166#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
167impl<'de> Deserialize<'de> for Limb {
168    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
169    where
170        D: Deserializer<'de>,
171    {
172        Ok(Self(Word::deserialize(deserializer)?))
173    }
174}
175
176#[cfg(feature = "serde")]
177#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
178impl<'de> Serialize for Limb {
179    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
180    where
181        S: Serializer,
182    {
183        self.0.serialize(serializer)
184    }
185}
186
187#[cfg(feature = "zeroize")]
188#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
189impl zeroize::DefaultIsZeroes for Limb {}