crypto_bigint/
wrapping.rs

1//! Wrapping arithmetic.
2
3use crate::{WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub, Zero};
4use core::{
5    fmt,
6    ops::{Add, Mul, Neg, Shl, Shr, Sub},
7};
8use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
9
10#[cfg(feature = "rand_core")]
11use {crate::Random, rand_core::RngCore};
12
13#[cfg(feature = "serde")]
14use serdect::serde::{Deserialize, Deserializer, Serialize, Serializer};
15
16/// Provides intentionally-wrapped arithmetic on `T`.
17///
18/// This is analogous to [`core::num::Wrapping`] but allows this crate to
19/// define trait impls for this type.
20#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
21pub struct Wrapping<T>(pub T);
22
23impl<T: WrappingAdd> Add<Self> for Wrapping<T> {
24    type Output = Wrapping<T>;
25
26    #[inline]
27    fn add(self, rhs: Self) -> Self::Output {
28        Wrapping(self.0.wrapping_add(&rhs.0))
29    }
30}
31
32impl<T: WrappingAdd> Add<&Self> for Wrapping<T> {
33    type Output = Wrapping<T>;
34
35    #[inline]
36    fn add(self, rhs: &Self) -> Self::Output {
37        Wrapping(self.0.wrapping_add(&rhs.0))
38    }
39}
40
41impl<T: WrappingAdd> Add<Wrapping<T>> for &Wrapping<T> {
42    type Output = Wrapping<T>;
43
44    #[inline]
45    fn add(self, rhs: Wrapping<T>) -> Self::Output {
46        Wrapping(self.0.wrapping_add(&rhs.0))
47    }
48}
49
50impl<T: WrappingAdd> Add<&Wrapping<T>> for &Wrapping<T> {
51    type Output = Wrapping<T>;
52
53    #[inline]
54    fn add(self, rhs: &Wrapping<T>) -> Self::Output {
55        Wrapping(self.0.wrapping_add(&rhs.0))
56    }
57}
58
59impl<T: WrappingSub> Sub<Self> for Wrapping<T> {
60    type Output = Wrapping<T>;
61
62    #[inline]
63    fn sub(self, rhs: Self) -> Self::Output {
64        Wrapping(self.0.wrapping_sub(&rhs.0))
65    }
66}
67
68impl<T: WrappingSub> Sub<&Self> for Wrapping<T> {
69    type Output = Wrapping<T>;
70
71    #[inline]
72    fn sub(self, rhs: &Self) -> Self::Output {
73        Wrapping(self.0.wrapping_sub(&rhs.0))
74    }
75}
76
77impl<T: WrappingSub> Sub<Wrapping<T>> for &Wrapping<T> {
78    type Output = Wrapping<T>;
79
80    #[inline]
81    fn sub(self, rhs: Wrapping<T>) -> Self::Output {
82        Wrapping(self.0.wrapping_sub(&rhs.0))
83    }
84}
85
86impl<T: WrappingSub> Sub<&Wrapping<T>> for &Wrapping<T> {
87    type Output = Wrapping<T>;
88
89    #[inline]
90    fn sub(self, rhs: &Wrapping<T>) -> Self::Output {
91        Wrapping(self.0.wrapping_sub(&rhs.0))
92    }
93}
94
95impl<T: WrappingMul> Mul<Self> for Wrapping<T> {
96    type Output = Wrapping<T>;
97
98    #[inline]
99    fn mul(self, rhs: Self) -> Self::Output {
100        Wrapping(self.0.wrapping_mul(&rhs.0))
101    }
102}
103
104impl<T: WrappingMul> Mul<&Self> for Wrapping<T> {
105    type Output = Wrapping<T>;
106
107    #[inline]
108    fn mul(self, rhs: &Self) -> Self::Output {
109        Wrapping(self.0.wrapping_mul(&rhs.0))
110    }
111}
112
113impl<T: WrappingMul> Mul<Wrapping<T>> for &Wrapping<T> {
114    type Output = Wrapping<T>;
115
116    #[inline]
117    fn mul(self, rhs: Wrapping<T>) -> Self::Output {
118        Wrapping(self.0.wrapping_mul(&rhs.0))
119    }
120}
121
122impl<T: WrappingMul> Mul<&Wrapping<T>> for &Wrapping<T> {
123    type Output = Wrapping<T>;
124
125    #[inline]
126    fn mul(self, rhs: &Wrapping<T>) -> Self::Output {
127        Wrapping(self.0.wrapping_mul(&rhs.0))
128    }
129}
130
131impl<T: WrappingNeg> Neg for Wrapping<T> {
132    type Output = Wrapping<T>;
133
134    #[inline]
135    fn neg(self) -> Self::Output {
136        Wrapping(self.0.wrapping_neg())
137    }
138}
139
140impl<T: WrappingNeg> Neg for &Wrapping<T> {
141    type Output = Wrapping<T>;
142
143    #[inline]
144    fn neg(self) -> Self::Output {
145        Wrapping(self.0.wrapping_neg())
146    }
147}
148
149impl<T: WrappingShl> Shl<u32> for Wrapping<T> {
150    type Output = Wrapping<T>;
151
152    #[inline]
153    fn shl(self, rhs: u32) -> Self::Output {
154        Wrapping(self.0.wrapping_shl(rhs))
155    }
156}
157
158impl<T: WrappingShl> Shl<u32> for &Wrapping<T> {
159    type Output = Wrapping<T>;
160
161    #[inline]
162    fn shl(self, rhs: u32) -> Self::Output {
163        Wrapping(self.0.wrapping_shl(rhs))
164    }
165}
166
167impl<T: WrappingShr> Shr<u32> for Wrapping<T> {
168    type Output = Wrapping<T>;
169
170    #[inline]
171    fn shr(self, rhs: u32) -> Self::Output {
172        Wrapping(self.0.wrapping_shr(rhs))
173    }
174}
175
176impl<T: WrappingShr> Shr<u32> for &Wrapping<T> {
177    type Output = Wrapping<T>;
178
179    #[inline]
180    fn shr(self, rhs: u32) -> Self::Output {
181        Wrapping(self.0.wrapping_shr(rhs))
182    }
183}
184
185impl<T: ConditionallySelectable> ConditionallySelectable for Wrapping<T> {
186    #[inline]
187    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
188        Wrapping(T::conditional_select(&a.0, &b.0, choice))
189    }
190}
191
192impl<T: ConstantTimeEq> ConstantTimeEq for Wrapping<T> {
193    #[inline]
194    fn ct_eq(&self, other: &Self) -> Choice {
195        self.0.ct_eq(&other.0)
196    }
197}
198
199impl<T: Zero> Zero for Wrapping<T> {
200    #[inline]
201    fn zero() -> Self {
202        Wrapping(T::zero())
203    }
204}
205
206impl<T: num_traits::Zero + WrappingAdd> num_traits::Zero for Wrapping<T> {
207    #[inline]
208    fn zero() -> Self {
209        Wrapping(T::zero())
210    }
211
212    #[inline]
213    fn is_zero(&self) -> bool {
214        self.0.is_zero()
215    }
216}
217
218impl<T: num_traits::One + WrappingMul + PartialEq> num_traits::One for Wrapping<T> {
219    #[inline]
220    fn one() -> Self {
221        Wrapping(T::one())
222    }
223
224    #[inline]
225    fn is_one(&self) -> bool {
226        self.0.is_one()
227    }
228}
229
230impl<T: fmt::Display> fmt::Display for Wrapping<T> {
231    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232        self.0.fmt(f)
233    }
234}
235
236impl<T: fmt::Binary> fmt::Binary for Wrapping<T> {
237    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
238        self.0.fmt(f)
239    }
240}
241
242impl<T: fmt::Octal> fmt::Octal for Wrapping<T> {
243    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244        self.0.fmt(f)
245    }
246}
247
248impl<T: fmt::LowerHex> fmt::LowerHex for Wrapping<T> {
249    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250        self.0.fmt(f)
251    }
252}
253
254impl<T: fmt::UpperHex> fmt::UpperHex for Wrapping<T> {
255    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256        self.0.fmt(f)
257    }
258}
259
260#[cfg(feature = "rand_core")]
261impl<T: Random> Random for Wrapping<T> {
262    fn random(rng: &mut (impl RngCore + ?Sized)) -> Self {
263        Wrapping(Random::random(rng))
264    }
265}
266
267#[cfg(feature = "serde")]
268impl<'de, T: Deserialize<'de>> Deserialize<'de> for Wrapping<T> {
269    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
270    where
271        D: Deserializer<'de>,
272    {
273        Ok(Self(T::deserialize(deserializer)?))
274    }
275}
276
277#[cfg(feature = "serde")]
278impl<T: Serialize> Serialize for Wrapping<T> {
279    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
280    where
281        S: Serializer,
282    {
283        self.0.serialize(serializer)
284    }
285}
286
287#[cfg(all(test, feature = "serde"))]
288#[allow(clippy::unwrap_used)]
289mod tests {
290    use crate::{Wrapping, U64};
291
292    #[test]
293    fn serde() {
294        const TEST: Wrapping<U64> = Wrapping(U64::from_u64(0x0011223344556677));
295
296        let serialized = bincode::serialize(&TEST).unwrap();
297        let deserialized: Wrapping<U64> = bincode::deserialize(&serialized).unwrap();
298
299        assert_eq!(TEST, deserialized);
300    }
301
302    #[test]
303    fn serde_owned() {
304        const TEST: Wrapping<U64> = Wrapping(U64::from_u64(0x0011223344556677));
305
306        let serialized = bincode::serialize(&TEST).unwrap();
307        let deserialized: Wrapping<U64> = bincode::deserialize_from(serialized.as_slice()).unwrap();
308
309        assert_eq!(TEST, deserialized);
310    }
311}