crypto_bigint/boxed/
uint.rs1mod add;
4mod cmp;
5
6use crate::{Limb, Word};
7use alloc::{vec, vec::Vec};
8use core::fmt;
9
10#[cfg(feature = "zeroize")]
11use zeroize::Zeroize;
12
13#[derive(Clone, Default)]
22pub struct BoxedUint {
23 limbs: Vec<Limb>,
25}
26
27impl BoxedUint {
28 pub fn zero() -> Self {
30 Self::default()
31 }
32
33 pub fn one() -> Self {
35 Self {
36 limbs: vec![Limb::ONE; 1],
37 }
38 }
39
40 pub fn new(bits_precision: usize) -> Option<Self> {
45 if bits_precision == 0 || bits_precision % Limb::BITS != 0 {
46 return None;
47 }
48
49 let nlimbs = bits_precision / Limb::BITS;
50
51 Some(Self {
52 limbs: vec![Limb::ZERO; nlimbs],
53 })
54 }
55
56 pub fn max(bits_precision: usize) -> Option<Self> {
61 let mut ret = Self::new(bits_precision)?;
62
63 for limb in &mut ret.limbs {
64 *limb = Limb::MAX;
65 }
66
67 Some(ret)
68 }
69
70 #[inline]
73 pub fn from_words(words: &[Word]) -> Self {
74 Self {
75 limbs: words.iter().copied().map(Into::into).collect(),
76 }
77 }
78
79 #[inline]
82 pub fn to_words(&self) -> Vec<Word> {
83 self.limbs.iter().copied().map(Into::into).collect()
84 }
85
86 pub fn as_words(&self) -> &[Word] {
88 #[allow(trivial_casts, unsafe_code)]
90 unsafe {
91 &*((self.limbs.as_slice() as *const _) as *const [Word])
92 }
93 }
94
95 pub fn as_words_mut(&mut self) -> &mut [Word] {
97 #[allow(trivial_casts, unsafe_code)]
99 unsafe {
100 &mut *((self.limbs.as_mut_slice() as *mut _) as *mut [Word])
101 }
102 }
103
104 pub fn as_limbs(&self) -> &[Limb] {
106 self.limbs.as_ref()
107 }
108
109 pub fn as_limbs_mut(&mut self) -> &mut [Limb] {
111 self.limbs.as_mut()
112 }
113
114 pub fn to_limbs(&self) -> Vec<Limb> {
116 self.limbs.clone()
117 }
118
119 pub fn into_limbs(self) -> Vec<Limb> {
121 self.limbs
122 }
123
124 pub fn bits(&self) -> usize {
126 self.limbs.len() * Limb::BITS
127 }
128
129 fn sort_by_precision<'a>(a: &'a Self, b: &'a Self) -> (&'a Self, &'a Self) {
133 if a.limbs.len() <= b.limbs.len() {
134 (a, b)
135 } else {
136 (b, a)
137 }
138 }
139
140 fn chain<F>(a: &Self, b: &Self, mut carry: Limb, f: F) -> (Self, Limb)
146 where
147 F: Fn(Limb, Limb, Limb) -> (Limb, Limb),
148 {
149 let (shorter, longer) = Self::sort_by_precision(a, b);
150 let mut limbs = Vec::with_capacity(longer.limbs.len());
151
152 for i in 0..longer.limbs.len() {
153 let &a = shorter.limbs.get(i).unwrap_or(&Limb::ZERO);
154 let &b = longer.limbs.get(i).unwrap_or(&Limb::ZERO);
155 let (limb, c) = f(a, b, carry);
156 limbs.push(limb);
157 carry = c;
158 }
159
160 (Self { limbs }, carry)
161 }
162}
163
164impl AsRef<[Word]> for BoxedUint {
165 fn as_ref(&self) -> &[Word] {
166 self.as_words()
167 }
168}
169
170impl AsMut<[Word]> for BoxedUint {
171 fn as_mut(&mut self) -> &mut [Word] {
172 self.as_words_mut()
173 }
174}
175
176impl AsRef<[Limb]> for BoxedUint {
177 fn as_ref(&self) -> &[Limb] {
178 self.as_limbs()
179 }
180}
181
182impl AsMut<[Limb]> for BoxedUint {
183 fn as_mut(&mut self) -> &mut [Limb] {
184 self.as_limbs_mut()
185 }
186}
187
188impl fmt::Debug for BoxedUint {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 write!(f, "BoxedUint(0x{self:X})")
191 }
192}
193
194impl fmt::Display for BoxedUint {
195 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196 fmt::UpperHex::fmt(self, f)
197 }
198}
199
200impl fmt::LowerHex for BoxedUint {
201 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202 if self.limbs.is_empty() {
203 return fmt::LowerHex::fmt(&Limb::ZERO, f);
204 }
205
206 for limb in self.limbs.iter().rev() {
207 fmt::LowerHex::fmt(limb, f)?;
208 }
209 Ok(())
210 }
211}
212
213impl fmt::UpperHex for BoxedUint {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 if self.limbs.is_empty() {
216 return fmt::LowerHex::fmt(&Limb::ZERO, f);
217 }
218
219 for limb in self.limbs.iter().rev() {
220 fmt::UpperHex::fmt(limb, f)?;
221 }
222 Ok(())
223 }
224}
225
226#[cfg(feature = "zeroize")]
227impl Zeroize for BoxedUint {
228 fn zeroize(&mut self) {
229 self.limbs.zeroize();
230 }
231}