Skip to content

Commit 876b125

Browse files
authored
Implement serde for Odd (#604)
1 parent 5167b12 commit 876b125

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

src/odd.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ use {crate::Random, rand_core::CryptoRngCore};
1313
#[cfg(all(feature = "alloc", feature = "rand_core"))]
1414
use crate::RandomBits;
1515

16+
#[cfg(feature = "serde")]
17+
use crate::Zero;
18+
#[cfg(feature = "serde")]
19+
use serdect::serde::{
20+
de::{Error, Unexpected},
21+
Deserialize, Deserializer, Serialize, Serializer,
22+
};
23+
1624
/// Wrapper type for odd integers.
1725
///
1826
/// These are frequently used in cryptography, e.g. as a modulus.
@@ -153,6 +161,30 @@ impl Odd<BoxedUint> {
153161
}
154162
}
155163

164+
#[cfg(feature = "serde")]
165+
impl<'de, T: Deserialize<'de> + Integer + Zero> Deserialize<'de> for Odd<T> {
166+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
167+
where
168+
D: Deserializer<'de>,
169+
{
170+
let value: T = T::deserialize(deserializer)?;
171+
Option::<Self>::from(Self::new(value)).ok_or(D::Error::invalid_value(
172+
Unexpected::Other("even"),
173+
&"a non-zero odd value",
174+
))
175+
}
176+
}
177+
178+
#[cfg(feature = "serde")]
179+
impl<T: Serialize + Zero> Serialize for Odd<T> {
180+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
181+
where
182+
S: Serializer,
183+
{
184+
self.0.serialize(serializer)
185+
}
186+
}
187+
156188
#[cfg(test)]
157189
mod tests {
158190
#[cfg(feature = "alloc")]
@@ -175,4 +207,68 @@ mod tests {
175207
let two = Odd::new(BoxedUint::from(2u8));
176208
assert!(bool::from(two.is_none()));
177209
}
210+
211+
#[cfg(feature = "serde")]
212+
mod serde_tests {
213+
use crate::{Odd, U128, U64};
214+
use alloc::string::ToString;
215+
use bincode::ErrorKind;
216+
217+
#[test]
218+
fn roundtrip() {
219+
let uint = Odd::new(U64::from_u64(0x00123)).unwrap();
220+
let ser = bincode::serialize(&uint).unwrap();
221+
let deser = bincode::deserialize::<Odd<U64>>(&ser).unwrap();
222+
223+
assert_eq!(uint, deser);
224+
}
225+
226+
#[test]
227+
fn even_values_do_not_deserialize() {
228+
let two = U128::from_u64(0x2);
229+
let two_ser = bincode::serialize(&two).unwrap();
230+
assert!(matches!(
231+
*bincode::deserialize::<Odd<U128>>(&two_ser).unwrap_err(),
232+
ErrorKind::Custom(mess) if mess == "invalid value: even, expected a non-zero odd value"
233+
))
234+
}
235+
236+
#[test]
237+
fn zero_does_not_deserialize() {
238+
let zero = U64::ZERO;
239+
let zero_ser = bincode::serialize(&zero).unwrap();
240+
241+
assert!(matches!(
242+
*bincode::deserialize::<Odd<U64>>(&zero_ser).unwrap_err(),
243+
ErrorKind::Custom(mess) if mess == "invalid value: even, expected a non-zero odd value"
244+
))
245+
}
246+
247+
#[test]
248+
fn cannot_deserialize_into_bigger_type() {
249+
let three = Odd::new(U64::from_u64(0x3)).unwrap();
250+
let three_ser = bincode::serialize(&three).unwrap();
251+
let error_message = bincode::deserialize::<Odd<U128>>(&three_ser)
252+
.unwrap_err()
253+
.to_string();
254+
255+
assert_eq!(&error_message, "io error: unexpected end of file");
256+
}
257+
258+
// @reviewers: I expected an error when deserializing an Odd<U128> into an Odd<U64>, instead I get a truncated number. Is this a big or known limitation?
259+
#[test]
260+
fn silently_coerces_bigger_type_into_smaller_type() {
261+
let three = Odd::new(U128::from_u128(0x77777777777777773333333333333333)).unwrap();
262+
263+
let three_ser = bincode::serialize(&three).unwrap();
264+
265+
// This doesn't fail, which is unexpected
266+
let smaller = bincode::deserialize::<Odd<U64>>(&three_ser).unwrap();
267+
268+
assert_eq!(
269+
smaller,
270+
Odd::new(U64::from_u64(0x3333333333333333)).unwrap()
271+
);
272+
}
273+
}
178274
}

0 commit comments

Comments
 (0)