1mod add;
5mod bit_and;
6mod bit_not;
7mod bit_or;
8mod bit_xor;
9mod bits;
10mod cmp;
11mod encoding;
12mod from;
13mod mul;
14mod neg;
15mod shl;
16mod shr;
17mod sub;
18
19#[cfg(feature = "rand_core")]
20mod rand;
21
22use crate::{Bounded, Zero};
23use core::fmt;
24use subtle::{Choice, ConditionallySelectable};
25
26#[cfg(feature = "serde")]
27use serdect::serde::{Deserialize, Deserializer, Serialize, Serializer};
28
29#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
30compile_error!("this crate builds on 32-bit and 64-bit platforms only");
31
32#[cfg(target_pointer_width = "32")]
38pub type Word = u32;
39
40#[cfg(target_pointer_width = "32")]
42pub type WideWord = u64;
43
44#[cfg(target_pointer_width = "64")]
50pub type Word = u64;
51
52#[cfg(target_pointer_width = "64")]
54pub type WideWord = u128;
55
56pub(crate) const HI_BIT: usize = Limb::BITS - 1;
58
59#[allow(clippy::derived_hash_with_manual_eq)]
63#[derive(Copy, Clone, Default, Hash)]
64#[repr(transparent)]
65pub struct Limb(pub Word);
66
67impl Limb {
68 pub const ZERO: Self = Limb(0);
70
71 pub const ONE: Self = Limb(1);
73
74 pub const MAX: Self = Limb(Word::MAX);
76
77 #[cfg(target_pointer_width = "32")]
81 pub const BITS: usize = 32;
82 #[cfg(target_pointer_width = "32")]
84 pub const BYTES: usize = 4;
85
86 #[cfg(target_pointer_width = "64")]
90 pub const BITS: usize = 64;
91 #[cfg(target_pointer_width = "64")]
93 pub const BYTES: usize = 8;
94}
95
96impl Bounded for Limb {
97 const BITS: usize = Self::BITS;
98 const BYTES: usize = Self::BYTES;
99}
100
101impl ConditionallySelectable for Limb {
102 #[inline]
103 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
104 Self(Word::conditional_select(&a.0, &b.0, choice))
105 }
106}
107
108impl Zero for Limb {
109 const ZERO: Self = Self::ZERO;
110}
111
112impl fmt::Debug for Limb {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 write!(f, "Limb(0x{self:X})")
115 }
116}
117
118impl fmt::Display for Limb {
119 #[inline]
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 fmt::UpperHex::fmt(self, f)
122 }
123}
124
125impl fmt::LowerHex for Limb {
126 #[inline]
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 write!(f, "{:0width$x}", &self.0, width = Self::BYTES * 2)
129 }
130}
131
132impl fmt::UpperHex for Limb {
133 #[inline]
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 write!(f, "{:0width$X}", &self.0, width = Self::BYTES * 2)
136 }
137}
138
139#[cfg(feature = "serde")]
140impl<'de> Deserialize<'de> for Limb {
141 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
142 where
143 D: Deserializer<'de>,
144 {
145 Ok(Self(Word::deserialize(deserializer)?))
146 }
147}
148
149#[cfg(feature = "serde")]
150impl Serialize for Limb {
151 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
152 where
153 S: Serializer,
154 {
155 self.0.serialize(serializer)
156 }
157}
158
159#[cfg(feature = "zeroize")]
160impl zeroize::DefaultIsZeroes for Limb {}
161
162#[cfg(test)]
163mod tests {
164 #[cfg(feature = "alloc")]
165 use {super::Limb, alloc::format};
166
167 #[cfg(feature = "alloc")]
168 #[test]
169 fn debug() {
170 #[cfg(target_pointer_width = "32")]
171 assert_eq!(format!("{:?}", Limb(42)), "Limb(0x0000002A)");
172
173 #[cfg(target_pointer_width = "64")]
174 assert_eq!(format!("{:?}", Limb(42)), "Limb(0x000000000000002A)");
175 }
176}