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