dashu_int/third_party/
rkyv_v08.rs1use alloc::vec::Vec;
11use rkyv_v08 as rkyv;
12
13use crate::{IBig, UBig, Word};
14use dashu_base::Sign;
15
16type WordArchived = <Word as rkyv::Archive>::Archived;
18
19impl rkyv::Archive for UBig {
20 type Archived = rkyv::vec::ArchivedVec<WordArchived>;
21 type Resolver = rkyv::vec::VecResolver;
22
23 fn resolve(&self, resolver: Self::Resolver, out: rkyv::Place<Self::Archived>) {
24 rkyv::vec::ArchivedVec::<WordArchived>::resolve_from_slice(self.as_words(), resolver, out);
25 }
26}
27
28impl<S: rkyv::rancor::Fallible + rkyv::ser::Allocator + rkyv::ser::Writer + ?Sized>
29 rkyv::Serialize<S> for UBig
30{
31 #[inline]
32 fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
33 rkyv::vec::ArchivedVec::<WordArchived>::serialize_from_slice(self.as_words(), serializer)
34 }
35}
36
37impl<D: rkyv::rancor::Fallible + ?Sized> rkyv::Deserialize<UBig, D>
38 for rkyv::vec::ArchivedVec<WordArchived>
39{
40 #[inline]
41 fn deserialize(&self, _: &mut D) -> Result<UBig, D::Error> {
42 let words: Vec<Word> = self.as_slice().iter().map(|w| w.to_native()).collect();
43 Ok(UBig::from_words(&words))
44 }
45}
46
47impl rkyv::Archive for IBig {
50 type Archived = rkyv::tuple::ArchivedTuple2<bool, rkyv::vec::ArchivedVec<WordArchived>>;
51 type Resolver = (<bool as rkyv::Archive>::Resolver, rkyv::vec::VecResolver);
52
53 #[allow(clippy::unit_arg)] fn resolve(&self, resolver: Self::Resolver, out: rkyv::Place<Self::Archived>) {
55 let (sign, words) = self.0.as_sign_slice();
56 unsafe {
57 let out_ptr = out.ptr();
61 let ptr = core::ptr::addr_of_mut!((*out_ptr).0);
62 let out_field = rkyv::Place::from_field_unchecked(out, ptr);
63 <bool as rkyv::Archive>::resolve(
64 &matches!(sign, Sign::Negative),
65 resolver.0,
66 out_field,
67 );
68 let ptr = core::ptr::addr_of_mut!((*out_ptr).1);
69 let out_field = rkyv::Place::from_field_unchecked(out, ptr);
70 rkyv::vec::ArchivedVec::<WordArchived>::resolve_from_slice(
71 words, resolver.1, out_field,
72 );
73 }
74 }
75}
76
77impl<S: rkyv::rancor::Fallible + rkyv::ser::Allocator + rkyv::ser::Writer + ?Sized>
78 rkyv::Serialize<S> for IBig
79{
80 #[inline]
81 fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
82 let (sign, words) = self.0.as_sign_slice();
83 <bool as rkyv::Serialize<S>>::serialize(&matches!(sign, Sign::Negative), serializer)?;
84 let words_resolver =
85 rkyv::vec::ArchivedVec::<WordArchived>::serialize_from_slice(words, serializer)?;
86 Ok(((), words_resolver))
87 }
88}
89
90impl<D: rkyv::rancor::Fallible + ?Sized> rkyv::Deserialize<IBig, D>
91 for rkyv::tuple::ArchivedTuple2<bool, rkyv::vec::ArchivedVec<WordArchived>>
92{
93 #[inline]
94 fn deserialize(&self, _: &mut D) -> Result<IBig, D::Error> {
95 let words: Vec<Word> = self.1.as_slice().iter().map(|w| w.to_native()).collect();
96 let mag = UBig::from_words(&words);
97 Ok(if self.0 {
98 -IBig::from(mag)
99 } else {
100 IBig::from(mag)
101 })
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn rkyv_ubig_roundtrip() {
111 let values = [
112 UBig::from(0u8),
113 UBig::from(1u8),
114 UBig::from(123456789u64),
115 UBig::from(1u8) << 100,
116 (UBig::from(3u8) << 300) + UBig::from(5u8),
117 ];
118 for v in &values {
119 let bytes = rkyv::to_bytes::<rkyv::rancor::Error>(v).unwrap();
120 let archived =
123 unsafe { rkyv::access_unchecked::<<UBig as rkyv::Archive>::Archived>(&bytes) };
124 let native: Vec<Word> = archived.as_slice().iter().map(|w| w.to_native()).collect();
125 assert_eq!(native, v.as_words(), "word view mismatch for {v}");
126 let v2 =
129 unsafe { rkyv::from_bytes_unchecked::<UBig, rkyv::rancor::Error>(&bytes) }.unwrap();
130 assert_eq!(v2, *v, "UBig round-trip failed for {v}");
131 }
132 }
133
134 #[test]
135 fn rkyv_ibig_roundtrip() {
136 let values = [
137 IBig::from(0),
138 IBig::from(-1),
139 IBig::from(1),
140 IBig::from(123456789i64),
141 IBig::from(-123456789i64),
142 (IBig::from(-1)) << 200,
143 ];
144 for v in &values {
145 let bytes = rkyv::to_bytes::<rkyv::rancor::Error>(v).unwrap();
146 let archived =
149 unsafe { rkyv::access_unchecked::<<IBig as rkyv::Archive>::Archived>(&bytes) };
150 assert_eq!(archived.0, v.sign() == Sign::Negative, "sign view mismatch for {v}");
151 let mag = v.clone().into_parts().1;
152 let native: Vec<Word> = archived
153 .1
154 .as_slice()
155 .iter()
156 .map(|w| w.to_native())
157 .collect();
158 assert_eq!(native, mag.as_words(), "word view mismatch for {v}");
159 let v2 =
162 unsafe { rkyv::from_bytes_unchecked::<IBig, rkyv::rancor::Error>(&bytes) }.unwrap();
163 assert_eq!(v2, *v, "IBig round-trip failed for {v}");
164 }
165 }
166}