primitives/algebra/
biguint.rs1use std::mem::MaybeUninit;
2
3use derive_more::derive::{AsMut, AsRef, Deref, DerefMut, From};
4use serde::{Deserialize, Serialize};
5use wincode::{io::Writer, ReadResult, SchemaRead, SchemaWrite, WriteResult};
6
7#[cfg(not(target_pointer_width = "64"))]
10compile_error!("this crate builds on 64-bit platforms only");
11
12#[derive(
14 Debug, Clone, Deref, DerefMut, PartialEq, Eq, Hash, AsRef, AsMut, From, PartialOrd, Ord,
15)]
16#[as_ref(forward)]
17#[from(forward)]
18#[repr(transparent)]
19pub struct BoxedUint(crypto_bigint::BoxedUint);
20
21impl Serialize for BoxedUint {
22 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
23 where
24 S: serde::Serializer,
25 {
26 let bytes = self.0.to_le_bytes();
27 bytes.serialize(serializer)
28 }
29}
30
31impl<'de> Deserialize<'de> for BoxedUint {
32 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
33 where
34 D: serde::Deserializer<'de>,
35 {
36 let bytes = Vec::<u8>::deserialize(deserializer)?;
37 let bits_precision = bytes.len() * 8;
38 let boxed_uint = crypto_bigint::BoxedUint::from_le_slice(&bytes, bits_precision as u32)
39 .map_err(serde::de::Error::custom)?;
40 Ok(BoxedUint(boxed_uint))
41 }
42}
43
44impl SchemaWrite for BoxedUint {
45 type Src = Self;
46
47 fn size_of(src: &Self::Src) -> WriteResult<usize> {
48 let limbs = src
49 .0
50 .as_limbs()
51 .iter()
52 .map(|limb| limb.0)
53 .collect::<Box<[u64]>>();
54 <Box<[u64]> as SchemaWrite>::size_of(&limbs)
55 }
56
57 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
58 let limbs = src
59 .0
60 .as_limbs()
61 .iter()
62 .map(|limb| limb.0)
63 .collect::<Box<[u64]>>();
64 <Box<[u64]> as SchemaWrite>::write(writer, &limbs)
65 }
66}
67
68impl<'de> SchemaRead<'de> for BoxedUint {
69 type Dst = Self;
70
71 fn read(
72 reader: &mut impl wincode::io::Reader<'de>,
73 dst: &mut MaybeUninit<Self::Dst>,
74 ) -> ReadResult<()> {
75 let dst_u64 = unsafe { &mut *dst.as_mut_ptr().cast::<MaybeUninit<Box<[u64]>>>() };
79 <Box<[u64]> as SchemaRead>::read(reader, dst_u64)?;
80 Ok(())
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use bincode;
88 use crypto_bigint::U256;
89
90 use super::BoxedUint;
91 #[test]
92 fn test_boxed_uint_bincode() {
93 let original = BoxedUint(crypto_bigint::BoxedUint::from(U256::from_u64(123456789)));
94 let serialized = bincode::serialize(&original).expect("Serialization failed");
95 let deserialized: BoxedUint =
96 bincode::deserialize(&serialized).expect("Deserialization failed");
97 assert_eq!(original, deserialized);
98 }
99
100 #[test]
101 fn test_boxed_uint_wincode() {
102 let original = BoxedUint(crypto_bigint::BoxedUint::from(U256::from_u64(123456789)));
103 let serialized = wincode::serialize(&original).expect("Serialization failed");
104 let deserialized: BoxedUint =
105 wincode::deserialize(&serialized).expect("Deserialization failed");
106 assert_eq!(original, deserialized);
107 }
108}