1#![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#[derive(Clone, Copy, Eq, PartialEq, Hash)]
17#[repr(transparent)]
18pub struct ArchivedUint<const BITS: usize, const LIMBS: usize>([ArchivedU64; LIMBS]);
19
20#[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}