diff options
Diffstat (limited to 'vendor/crypto-bigint/src/limb.rs')
-rw-r--r-- | vendor/crypto-bigint/src/limb.rs | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/vendor/crypto-bigint/src/limb.rs b/vendor/crypto-bigint/src/limb.rs new file mode 100644 index 0000000..a5ca957 --- /dev/null +++ b/vendor/crypto-bigint/src/limb.rs @@ -0,0 +1,176 @@ +//! Big integers are represented as an array of smaller CPU word-size integers +//! called "limbs". + +mod add; +mod bit_and; +mod bit_not; +mod bit_or; +mod bit_xor; +mod bits; +mod cmp; +mod encoding; +mod from; +mod mul; +mod neg; +mod shl; +mod shr; +mod sub; + +#[cfg(feature = "rand_core")] +mod rand; + +use crate::{Bounded, Zero}; +use core::fmt; +use subtle::{Choice, ConditionallySelectable}; + +#[cfg(feature = "serde")] +use serdect::serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))] +compile_error!("this crate builds on 32-bit and 64-bit platforms only"); + +// +// 32-bit definitions +// + +/// Inner integer type that the [`Limb`] newtype wraps. +#[cfg(target_pointer_width = "32")] +pub type Word = u32; + +/// Unsigned wide integer type: double the width of [`Word`]. +#[cfg(target_pointer_width = "32")] +pub type WideWord = u64; + +// +// 64-bit definitions +// + +/// Unsigned integer type that the [`Limb`] newtype wraps. +#[cfg(target_pointer_width = "64")] +pub type Word = u64; + +/// Wide integer type: double the width of [`Word`]. +#[cfg(target_pointer_width = "64")] +pub type WideWord = u128; + +/// Highest bit in a [`Limb`]. +pub(crate) const HI_BIT: usize = Limb::BITS - 1; + +/// Big integers are represented as an array of smaller CPU word-size integers +/// called "limbs". +// Our PartialEq impl only differs from the default one by being constant-time, so this is safe +#[allow(clippy::derived_hash_with_manual_eq)] +#[derive(Copy, Clone, Default, Hash)] +#[repr(transparent)] +pub struct Limb(pub Word); + +impl Limb { + /// The value `0`. + pub const ZERO: Self = Limb(0); + + /// The value `1`. + pub const ONE: Self = Limb(1); + + /// Maximum value this [`Limb`] can express. + pub const MAX: Self = Limb(Word::MAX); + + // 32-bit + + /// Size of the inner integer in bits. + #[cfg(target_pointer_width = "32")] + pub const BITS: usize = 32; + /// Size of the inner integer in bytes. + #[cfg(target_pointer_width = "32")] + pub const BYTES: usize = 4; + + // 64-bit + + /// Size of the inner integer in bits. + #[cfg(target_pointer_width = "64")] + pub const BITS: usize = 64; + /// Size of the inner integer in bytes. + #[cfg(target_pointer_width = "64")] + pub const BYTES: usize = 8; +} + +impl Bounded for Limb { + const BITS: usize = Self::BITS; + const BYTES: usize = Self::BYTES; +} + +impl ConditionallySelectable for Limb { + #[inline] + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + Self(Word::conditional_select(&a.0, &b.0, choice)) + } +} + +impl Zero for Limb { + const ZERO: Self = Self::ZERO; +} + +impl fmt::Debug for Limb { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Limb(0x{self:X})") + } +} + +impl fmt::Display for Limb { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::UpperHex::fmt(self, f) + } +} + +impl fmt::LowerHex for Limb { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:0width$x}", &self.0, width = Self::BYTES * 2) + } +} + +impl fmt::UpperHex for Limb { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:0width$X}", &self.0, width = Self::BYTES * 2) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for Limb { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + Ok(Self(Word::deserialize(deserializer)?)) + } +} + +#[cfg(feature = "serde")] +impl Serialize for Limb { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + self.0.serialize(serializer) + } +} + +#[cfg(feature = "zeroize")] +impl zeroize::DefaultIsZeroes for Limb {} + +#[cfg(test)] +mod tests { + #[cfg(feature = "alloc")] + use {super::Limb, alloc::format}; + + #[cfg(feature = "alloc")] + #[test] + fn debug() { + #[cfg(target_pointer_width = "32")] + assert_eq!(format!("{:?}", Limb(42)), "Limb(0x0000002A)"); + + #[cfg(target_pointer_width = "64")] + assert_eq!(format!("{:?}", Limb(42)), "Limb(0x000000000000002A)"); + } +} |