dashu_int/third_party/
rkyv_v07.rs1use rkyv_v07 as rkyv;
18
19use crate::{IBig, UBig, Word};
20use dashu_base::Sign;
21
22impl rkyv::Archive for UBig {
23 type Archived = rkyv::vec::ArchivedVec<Word>;
24 type Resolver = rkyv::vec::VecResolver;
25
26 #[inline]
27 unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
28 rkyv::vec::ArchivedVec::<Word>::resolve_from_slice(self.as_words(), pos, resolver, out);
29 }
30}
31
32impl<S: rkyv::ser::Serializer + rkyv::ser::ScratchSpace + ?Sized> rkyv::Serialize<S> for UBig {
33 #[inline]
34 fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
35 rkyv::vec::ArchivedVec::<Word>::serialize_from_slice(self.as_words(), serializer)
36 }
37}
38
39impl<D: rkyv::Fallible + ?Sized> rkyv::Deserialize<UBig, D> for rkyv::vec::ArchivedVec<Word> {
40 #[inline]
41 fn deserialize(&self, _: &mut D) -> Result<UBig, D::Error> {
42 Ok(UBig::from_words(self.as_slice()))
43 }
44}
45
46impl rkyv::Archive for IBig {
50 type Archived = (bool, rkyv::vec::ArchivedVec<Word>);
51 type Resolver = ((), rkyv::vec::VecResolver);
52
53 #[inline]
54 #[allow(clippy::unit_arg)] unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
56 let (sign, words) = self.0.as_sign_slice();
57 let (fp0, fo0) = rkyv::out_field!(out.0);
58 <bool as rkyv::Archive>::resolve(
59 &matches!(sign, Sign::Negative),
60 pos + fp0,
61 resolver.0,
62 fo0,
63 );
64 let (fp1, fo1) = rkyv::out_field!(out.1);
65 rkyv::vec::ArchivedVec::<Word>::resolve_from_slice(words, pos + fp1, resolver.1, fo1);
66 }
67}
68
69impl<S: rkyv::ser::Serializer + rkyv::ser::ScratchSpace + ?Sized> rkyv::Serialize<S> for IBig {
70 #[inline]
71 fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
72 let (sign, words) = self.0.as_sign_slice();
73 <bool as rkyv::Serialize<S>>::serialize(&matches!(sign, Sign::Negative), serializer)?;
74 let words_resolver =
75 rkyv::vec::ArchivedVec::<Word>::serialize_from_slice(words, serializer)?;
76 Ok(((), words_resolver))
77 }
78}
79
80impl<D: rkyv::Fallible + ?Sized> rkyv::Deserialize<IBig, D>
81 for (bool, rkyv::vec::ArchivedVec<Word>)
82{
83 #[inline]
84 fn deserialize(&self, _: &mut D) -> Result<IBig, D::Error> {
85 let mag = UBig::from_words(self.1.as_slice());
87 Ok(if self.0 {
88 -IBig::from(mag)
89 } else {
90 IBig::from(mag)
91 })
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn rkyv_ubig_roundtrip() {
101 let values = [
102 UBig::from(0u8),
103 UBig::from(1u8),
104 UBig::from(123456789u64),
105 UBig::from(1u8) << 100,
106 (UBig::from(3u8) << 300) + UBig::from(5u8),
107 ];
108 for v in &values {
109 let bytes = rkyv::to_bytes::<_, 512>(v).unwrap();
110 let archived = unsafe { rkyv::archived_root::<UBig>(&bytes) };
113 assert_eq!(archived.as_slice(), v.as_words(), "word view mismatch for {v}");
115 let v2 = unsafe { rkyv::from_bytes_unchecked::<UBig>(&bytes) }.unwrap();
118 assert_eq!(v2, *v, "UBig round-trip failed for {v}");
119 }
120 }
121
122 #[test]
123 fn rkyv_ibig_roundtrip() {
124 let values = [
125 IBig::from(0),
126 IBig::from(-1),
127 IBig::from(1),
128 IBig::from(123456789i64),
129 IBig::from(-123456789i64),
130 (IBig::from(-1)) << 200,
131 ];
132 for v in &values {
133 let bytes = rkyv::to_bytes::<_, 512>(v).unwrap();
134 let archived = unsafe { rkyv::archived_root::<IBig>(&bytes) };
137 assert_eq!(archived.0, v.sign() == Sign::Negative, "sign view mismatch for {v}");
139 let mag = v.clone().into_parts().1;
140 assert_eq!(archived.1.as_slice(), mag.as_words(), "word view mismatch for {v}");
141 let v2 = unsafe { rkyv::from_bytes_unchecked::<IBig>(&bytes) }.unwrap();
144 assert_eq!(v2, *v, "IBig round-trip failed for {v}");
145 }
146 }
147}