1 use super::{biguint_from_vec, BigUint};
2 
3 use crate::std_alloc::Vec;
4 
5 use core::{cmp, fmt, mem};
6 use serde::de::{SeqAccess, Visitor};
7 use serde::{Deserialize, Deserializer, Serialize, Serializer};
8 
9 // `cautious` is based on the function of the same name in `serde`, but specialized to `u32`:
10 // https://github.com/dtolnay/serde/blob/399ef081ecc36d2f165ff1f6debdcbf6a1dc7efb/serde/src/private/size_hint.rs#L11-L22
cautious(hint: Option<usize>) -> usize11 fn cautious(hint: Option<usize>) -> usize {
12     const MAX_PREALLOC_BYTES: usize = 1024 * 1024;
13 
14     cmp::min(
15         hint.unwrap_or(0),
16         MAX_PREALLOC_BYTES / mem::size_of::<u32>(),
17     )
18 }
19 
20 impl Serialize for BigUint {
21     #[cfg(not(u64_digit))]
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,22     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
23     where
24         S: Serializer,
25     {
26         // Note: do not change the serialization format, or it may break forward
27         // and backward compatibility of serialized data!  If we ever change the
28         // internal representation, we should still serialize in base-`u32`.
29         let data: &[u32] = &self.data;
30         data.serialize(serializer)
31     }
32 
33     #[cfg(u64_digit)]
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,34     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
35     where
36         S: Serializer,
37     {
38         use serde::ser::SerializeSeq;
39 
40         if let Some((&last, data)) = self.data.split_last() {
41             let last_lo = last as u32;
42             let last_hi = (last >> 32) as u32;
43             let u32_len = data.len() * 2 + 1 + (last_hi != 0) as usize;
44             let mut seq = serializer.serialize_seq(Some(u32_len))?;
45             for &x in data {
46                 seq.serialize_element(&(x as u32))?;
47                 seq.serialize_element(&((x >> 32) as u32))?;
48             }
49             seq.serialize_element(&last_lo)?;
50             if last_hi != 0 {
51                 seq.serialize_element(&last_hi)?;
52             }
53             seq.end()
54         } else {
55             let data: &[u32] = &[];
56             data.serialize(serializer)
57         }
58     }
59 }
60 
61 impl<'de> Deserialize<'de> for BigUint {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,62     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
63     where
64         D: Deserializer<'de>,
65     {
66         deserializer.deserialize_seq(U32Visitor)
67     }
68 }
69 
70 struct U32Visitor;
71 
72 impl<'de> Visitor<'de> for U32Visitor {
73     type Value = BigUint;
74 
expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result75     fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
76         formatter.write_str("a sequence of unsigned 32-bit numbers")
77     }
78 
79     #[cfg(not(u64_digit))]
visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error> where S: SeqAccess<'de>,80     fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
81     where
82         S: SeqAccess<'de>,
83     {
84         let len = cautious(seq.size_hint());
85         let mut data = Vec::with_capacity(len);
86 
87         while let Some(value) = seq.next_element::<u32>()? {
88             data.push(value);
89         }
90 
91         Ok(biguint_from_vec(data))
92     }
93 
94     #[cfg(u64_digit)]
visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error> where S: SeqAccess<'de>,95     fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
96     where
97         S: SeqAccess<'de>,
98     {
99         use crate::big_digit::BigDigit;
100         use num_integer::Integer;
101 
102         let u32_len = cautious(seq.size_hint());
103         let len = Integer::div_ceil(&u32_len, &2);
104         let mut data = Vec::with_capacity(len);
105 
106         while let Some(lo) = seq.next_element::<u32>()? {
107             let mut value = BigDigit::from(lo);
108             if let Some(hi) = seq.next_element::<u32>()? {
109                 value |= BigDigit::from(hi) << 32;
110                 data.push(value);
111             } else {
112                 data.push(value);
113                 break;
114             }
115         }
116 
117         Ok(biguint_from_vec(data))
118     }
119 }
120