Skip to main content

ruint/support/
rkyv.rs

1//! Support for the [rkyv](https://github.com/rkyv/rkyv) crate.
2
3#![cfg(feature = "rkyv")]
4#![cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
5
6use crate::{Bits, Uint};
7use core::fmt;
8use rkyv::{
9    Archive, Archived, Deserialize, Place, Portable, Serialize,
10    bytecheck::CheckBytes,
11    primitive::ArchivedU64,
12    rancor::{Fallible, Trace},
13};
14
15/// An archived [`Uint`]
16#[derive(Clone, Copy, Eq, PartialEq, Hash)]
17#[repr(transparent)]
18pub struct ArchivedUint<const BITS: usize, const LIMBS: usize>([ArchivedU64; LIMBS]);
19
20/// An archived [`Bits`]
21#[derive(Clone, Copy, Eq, PartialEq, Hash)]
22#[repr(transparent)]
23pub struct ArchivedBits<const BITS: usize, const LIMBS: usize>(ArchivedUint<BITS, LIMBS>);
24
25unsafe impl<const BITS: usize, const LIMBS: usize, C: Fallible + ?Sized> CheckBytes<C>
26    for ArchivedUint<BITS, LIMBS>
27where
28    <C as Fallible>::Error: Trace,
29{
30    unsafe fn check_bytes(
31        value: *const Self,
32        context: &mut C,
33    ) -> Result<(), <C as Fallible>::Error> {
34        unsafe {
35            <[ArchivedU64; LIMBS]>::check_bytes(value.cast(), context)?;
36        }
37        Ok(())
38    }
39}
40
41impl<const BITS: usize, const LIMBS: usize> Archive for Uint<BITS, LIMBS> {
42    type Archived = ArchivedUint<BITS, LIMBS>;
43    type Resolver = [(); LIMBS];
44
45    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
46        self.limbs
47            .resolve(resolver, unsafe { out.cast_unchecked() });
48    }
49}
50
51unsafe impl<const BITS: usize, const LIMBS: usize> Portable for ArchivedUint<BITS, LIMBS> {}
52
53impl<S: Fallible + ?Sized, const BITS: usize, const LIMBS: usize> Serialize<S>
54    for Uint<BITS, LIMBS>
55{
56    fn serialize(&self, serializer: &mut S) -> Result<[(); LIMBS], <S as Fallible>::Error> {
57        self.limbs.serialize(serializer)
58    }
59}
60
61impl<D: Fallible + ?Sized, const BITS: usize, const LIMBS: usize> Deserialize<Uint<BITS, LIMBS>, D>
62    for Archived<Uint<BITS, LIMBS>>
63{
64    fn deserialize(
65        &self,
66        deserializer: &mut D,
67    ) -> Result<Uint<BITS, LIMBS>, <D as Fallible>::Error> {
68        Ok(Uint {
69            limbs: <[ArchivedU64; LIMBS]>::deserialize(&self.0, deserializer)?,
70        })
71    }
72}
73
74unsafe impl<const BITS: usize, const LIMBS: usize, C: Fallible + ?Sized> CheckBytes<C>
75    for ArchivedBits<BITS, LIMBS>
76where
77    <C as Fallible>::Error: Trace,
78{
79    unsafe fn check_bytes(
80        value: *const Self,
81        context: &mut C,
82    ) -> Result<(), <C as Fallible>::Error> {
83        unsafe {
84            <ArchivedUint<BITS, LIMBS>>::check_bytes(value.cast(), context)?;
85        }
86        Ok(())
87    }
88}
89
90impl<const BITS: usize, const LIMBS: usize> Archive for Bits<BITS, LIMBS> {
91    type Archived = ArchivedBits<BITS, LIMBS>;
92    type Resolver = [(); LIMBS];
93
94    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
95        self.as_uint()
96            .resolve(resolver, unsafe { out.cast_unchecked() });
97    }
98}
99
100unsafe impl<const BITS: usize, const LIMBS: usize> Portable for ArchivedBits<BITS, LIMBS> {}
101
102impl<S: Fallible + ?Sized, const BITS: usize, const LIMBS: usize> Serialize<S>
103    for Bits<BITS, LIMBS>
104{
105    fn serialize(&self, serializer: &mut S) -> Result<[(); LIMBS], <S as Fallible>::Error> {
106        self.as_uint().serialize(serializer)
107    }
108}
109
110impl<D: Fallible + ?Sized, const BITS: usize, const LIMBS: usize> Deserialize<Bits<BITS, LIMBS>, D>
111    for Archived<Bits<BITS, LIMBS>>
112{
113    fn deserialize(
114        &self,
115        deserializer: &mut D,
116    ) -> Result<Bits<BITS, LIMBS>, <D as Fallible>::Error> {
117        Ok(Bits::from(
118            Deserialize::<Uint<BITS, LIMBS>, D>::deserialize(&self.0, deserializer)?,
119        ))
120    }
121}
122
123impl<'a, const BITS: usize, const LIMBS: usize> From<&'a ArchivedUint<BITS, LIMBS>>
124    for Uint<BITS, LIMBS>
125{
126    fn from(archived: &'a ArchivedUint<BITS, LIMBS>) -> Self {
127        Self {
128            limbs: archived.0.map(ArchivedU64::to_native),
129        }
130    }
131}
132
133impl<'a, const BITS: usize, const LIMBS: usize> From<&'a ArchivedBits<BITS, LIMBS>>
134    for Bits<BITS, LIMBS>
135{
136    fn from(archived: &'a ArchivedBits<BITS, LIMBS>) -> Self {
137        Self::from(Into::<Uint<BITS, LIMBS>>::into(archived.0))
138    }
139}
140
141impl<const BITS: usize, const LIMBS: usize> From<ArchivedUint<BITS, LIMBS>> for Uint<BITS, LIMBS> {
142    fn from(archived: ArchivedUint<BITS, LIMBS>) -> Self {
143        (&archived).into()
144    }
145}
146
147impl<const BITS: usize, const LIMBS: usize> fmt::Display for ArchivedUint<BITS, LIMBS> {
148    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149        fmt::Display::fmt(&Into::<Uint<BITS, LIMBS>>::into(self), f)
150    }
151}
152
153impl<const BITS: usize, const LIMBS: usize> fmt::Debug for ArchivedUint<BITS, LIMBS> {
154    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155        fmt::Debug::fmt(&Into::<Uint<BITS, LIMBS>>::into(self), f)
156    }
157}
158
159impl<const BITS: usize, const LIMBS: usize> fmt::Binary for ArchivedUint<BITS, LIMBS> {
160    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161        fmt::Binary::fmt(&Into::<Uint<BITS, LIMBS>>::into(self), f)
162    }
163}
164
165impl<const BITS: usize, const LIMBS: usize> fmt::Octal for ArchivedUint<BITS, LIMBS> {
166    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167        fmt::Octal::fmt(&Into::<Uint<BITS, LIMBS>>::into(self), f)
168    }
169}
170
171impl<const BITS: usize, const LIMBS: usize> fmt::LowerHex for ArchivedUint<BITS, LIMBS> {
172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173        fmt::LowerHex::fmt(&Into::<Uint<BITS, LIMBS>>::into(self), f)
174    }
175}
176
177impl<const BITS: usize, const LIMBS: usize> fmt::UpperHex for ArchivedUint<BITS, LIMBS> {
178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179        fmt::UpperHex::fmt(&Into::<Uint<BITS, LIMBS>>::into(self), f)
180    }
181}
182
183#[cfg(test)]
184mod tests {
185    use super::*;
186    use crate::{Uint, const_for, nlimbs};
187    use proptest::proptest;
188    use rkyv::rancor;
189
190    #[test]
191    fn test_rkyv() {
192        const_for!(BITS in NON_ZERO {
193            const LIMBS: usize = nlimbs(BITS);
194            proptest!(|(n: Uint<BITS, LIMBS>)| {
195                let s = rkyv::to_bytes::<rancor::Error>(&n).unwrap();
196                let a = rkyv::access::<ArchivedUint<BITS, LIMBS>, rancor::Error>(&s).unwrap();
197                assert_eq!(n, Into::<Uint<BITS, LIMBS>>::into(a));
198                let d = rkyv::deserialize::<_, rancor::Error>(a).unwrap();
199                assert_eq!(n, d);
200
201                let b = Bits::from(n);
202                let s = rkyv::to_bytes::<rancor::Error>(&b).unwrap();
203                let a = rkyv::access::<ArchivedBits<BITS, LIMBS>, rancor::Error>(&s).unwrap();
204                assert_eq!(b, a.into());
205                let d = rkyv::deserialize::<_, rancor::Error>(a).unwrap();
206                assert_eq!(b, d);
207            });
208        });
209    }
210}