diff --git a/Cargo.lock b/Cargo.lock index ea2da98b..4e545cd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -714,9 +714,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.138" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", diff --git a/Cargo.toml b/Cargo.toml index 48a91f76..d28092f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,6 @@ proptest = "1.5" rand_core = { version = "0.9", features = ["std", "os_rng"] } rand_chacha = "0.9" - [features] default = ["rand"] alloc = ["serdect?/alloc"] diff --git a/src/uint/boxed/encoding.rs b/src/uint/boxed/encoding.rs index 85d7b0e9..357372a8 100644 --- a/src/uint/boxed/encoding.rs +++ b/src/uint/boxed/encoding.rs @@ -5,6 +5,9 @@ use crate::{DecodeError, Limb, Word, uint::encoding}; use alloc::{boxed::Box, string::String, vec::Vec}; use subtle::{Choice, CtOption}; +#[cfg(feature = "serde")] +mod serde; + impl BoxedUint { /// Create a new [`BoxedUint`] from the provided big endian bytes. /// diff --git a/src/uint/boxed/encoding/serde.rs b/src/uint/boxed/encoding/serde.rs new file mode 100644 index 00000000..845579ee --- /dev/null +++ b/src/uint/boxed/encoding/serde.rs @@ -0,0 +1,71 @@ +use serdect::serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error}; + +use crate::BoxedUint; + +impl<'de> Deserialize<'de> for BoxedUint { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let slice = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + let bit_precision = (slice.len() as u32).checked_mul(8).ok_or(Error::custom( + "Deserialized value overflows u32 bit precision!", + ))?; + Self::from_le_slice(&slice, bit_precision).map_err(Error::custom) + } +} + +impl Serialize for BoxedUint { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serdect::slice::serialize_hex_lower_or_bin(&self.to_le_bytes(), serializer) + } +} + +#[cfg(test)] +mod tests { + use super::BoxedUint; + #[cfg(target_pointer_width = "32")] + use crate::Limb; + #[cfg(target_pointer_width = "32")] + use hex_literal::hex; + + #[test] + #[cfg(target_pointer_width = "64")] + fn serde() { + let test: BoxedUint = BoxedUint::from_be_hex("7711223344556600", 64).unwrap(); + + let serialized = bincode::serialize(&test).unwrap(); + let deserialized: BoxedUint = bincode::deserialize(&serialized).unwrap(); + + assert_eq!(test, deserialized); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn serde_owned() { + let test: BoxedUint = BoxedUint::from_be_hex("7711223344556600", 64).unwrap(); + + let serialized = bincode::serialize(&test).unwrap(); + let deserialized: BoxedUint = bincode::deserialize_from(serialized.as_slice()).unwrap(); + + assert_eq!(test, deserialized); + } + + #[test] + #[cfg(target_pointer_width = "32")] + fn from_le_slice_eq_test() { + let bytes = hex!("7766554433221100"); + let box_uint = BoxedUint::from_le_slice(&bytes, 64).unwrap(); + + let serialized = bincode::serialize(&box_uint).unwrap(); + let deserialized: BoxedUint = bincode::deserialize_from(serialized.as_slice()).unwrap(); + + assert_eq!( + deserialized.as_limbs(), + &[Limb(0x44556677), Limb(0x00112233)] + ); + } +}