serde_with/
utils.rs

1pub(crate) mod duration;
2
3use crate::prelude::*;
4
5/// Re-Implementation of `serde::private::de::size_hint::cautious`
6#[cfg(feature = "alloc")]
7#[inline]
8pub(crate) fn size_hint_cautious<Element>(hint: Option<usize>) -> usize {
9    const MAX_PREALLOC_BYTES: usize = 1024 * 1024;
10
11    if core::mem::size_of::<Element>() == 0 {
12        0
13    } else {
14        core::cmp::min(
15            hint.unwrap_or(0),
16            MAX_PREALLOC_BYTES / core::mem::size_of::<Element>(),
17        )
18    }
19}
20
21/// Re-Implementation of `serde::private::de::size_hint::from_bounds`
22#[cfg(feature = "alloc")]
23#[inline]
24pub fn size_hint_from_bounds<I>(iter: &I) -> Option<usize>
25where
26    I: Iterator,
27{
28    fn _size_hint_from_bounds(bounds: (usize, Option<usize>)) -> Option<usize> {
29        match bounds {
30            (lower, Some(upper)) if lower == upper => Some(upper),
31            _ => None,
32        }
33    }
34    _size_hint_from_bounds(iter.size_hint())
35}
36
37pub(crate) const NANOS_PER_SEC: u128 = 1_000_000_000;
38pub(crate) const NANOS_PER_SEC_F64: f64 = 1_000_000_000.0;
39// pub(crate) const NANOS_PER_MILLI: u32 = 1_000_000;
40// pub(crate) const NANOS_PER_MICRO: u32 = 1_000;
41// pub(crate) const MILLIS_PER_SEC: u64 = 1_000;
42// pub(crate) const MICROS_PER_SEC: u64 = 1_000_000;
43pub(crate) const U64_MAX: u128 = u64::MAX as u128;
44
45pub(crate) struct MapIter<'de, A, K, V> {
46    pub(crate) access: A,
47    marker: PhantomData<(&'de (), K, V)>,
48}
49
50impl<'de, A, K, V> MapIter<'de, A, K, V> {
51    pub(crate) fn new(access: A) -> Self
52    where
53        A: MapAccess<'de>,
54    {
55        Self {
56            access,
57            marker: PhantomData,
58        }
59    }
60}
61
62impl<'de, A, K, V> Iterator for MapIter<'de, A, K, V>
63where
64    A: MapAccess<'de>,
65    K: Deserialize<'de>,
66    V: Deserialize<'de>,
67{
68    type Item = Result<(K, V), A::Error>;
69
70    fn next(&mut self) -> Option<Self::Item> {
71        self.access.next_entry().transpose()
72    }
73
74    fn size_hint(&self) -> (usize, Option<usize>) {
75        match self.access.size_hint() {
76            Some(size) => (size, Some(size)),
77            None => (0, None),
78        }
79    }
80}
81
82pub(crate) struct SeqIter<'de, A, T> {
83    access: A,
84    marker: PhantomData<(&'de (), T)>,
85}
86
87impl<'de, A, T> SeqIter<'de, A, T> {
88    pub(crate) fn new(access: A) -> Self
89    where
90        A: SeqAccess<'de>,
91    {
92        Self {
93            access,
94            marker: PhantomData,
95        }
96    }
97}
98
99impl<'de, A, T> Iterator for SeqIter<'de, A, T>
100where
101    A: SeqAccess<'de>,
102    T: Deserialize<'de>,
103{
104    type Item = Result<T, A::Error>;
105
106    fn next(&mut self) -> Option<Self::Item> {
107        self.access.next_element().transpose()
108    }
109
110    fn size_hint(&self) -> (usize, Option<usize>) {
111        match self.access.size_hint() {
112            Some(size) => (size, Some(size)),
113            None => (0, None),
114        }
115    }
116}
117
118pub(crate) fn duration_signed_from_secs_f64(secs: f64) -> Result<DurationSigned, &'static str> {
119    const MAX_NANOS_F64: f64 = ((U64_MAX + 1) * NANOS_PER_SEC) as f64;
120    // TODO why are the seconds converted to nanoseconds first?
121    // Does it make sense to just truncate the value?
122    let mut nanos = secs * NANOS_PER_SEC_F64;
123    if !nanos.is_finite() {
124        return Err("got non-finite value when converting float to duration");
125    }
126    if nanos >= MAX_NANOS_F64 {
127        return Err("overflow when converting float to duration");
128    }
129    let mut sign = Sign::Positive;
130    if nanos < 0.0 {
131        nanos = -nanos;
132        sign = Sign::Negative;
133    }
134    let nanos = nanos as u128;
135    Ok(DurationSigned::new(
136        sign,
137        (nanos / NANOS_PER_SEC) as u64,
138        (nanos % NANOS_PER_SEC) as u32,
139    ))
140}
141
142/// Collect an array of a fixed size from an iterator.
143///
144/// # Safety
145/// The code follow exactly the pattern of initializing an array element-by-element from the standard library.
146/// <https://doc.rust-lang.org/nightly/std/mem/union.MaybeUninit.html#initializing-an-array-element-by-element>
147pub(crate) fn array_from_iterator<I, T, E, const N: usize>(
148    mut iter: I,
149    expected: &dyn Expected,
150) -> Result<[T; N], E>
151where
152    I: Iterator<Item = Result<T, E>>,
153    E: DeError,
154{
155    use core::mem::MaybeUninit;
156
157    fn drop_array_elems<T, const N: usize>(num: usize, mut arr: [MaybeUninit<T>; N]) {
158        arr[..num].iter_mut().for_each(|elem| {
159            // TODO This would be better with assume_init_drop nightly function
160            // https://github.com/rust-lang/rust/issues/63567
161            unsafe { core::ptr::drop_in_place(elem.as_mut_ptr()) };
162        });
163    }
164
165    // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
166    // safe because the type we are claiming to have initialized here is a
167    // bunch of `MaybeUninit`s, which do not require initialization.
168    //
169    // TODO could be simplified with nightly maybe_uninit_uninit_array feature
170    // https://doc.rust-lang.org/nightly/std/mem/union.MaybeUninit.html#method.uninit_array
171
172    let mut arr: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
173
174    // Dropping a `MaybeUninit` does nothing. Thus using raw pointer
175    // assignment instead of `ptr::write` does not cause the old
176    // uninitialized value to be dropped. Also if there is a panic during
177    // this loop, we have a memory leak, but there is no memory safety
178    // issue.
179    for (idx, elem) in arr[..].iter_mut().enumerate() {
180        *elem = match iter.next() {
181            Some(Ok(value)) => MaybeUninit::new(value),
182            Some(Err(err)) => {
183                drop_array_elems(idx, arr);
184                return Err(err);
185            }
186            None => {
187                drop_array_elems(idx, arr);
188                return Err(DeError::invalid_length(idx, expected));
189            }
190        };
191    }
192
193    // Everything is initialized. Transmute the array to the
194    // initialized type.
195    // A normal transmute is not possible because of:
196    // https://github.com/rust-lang/rust/issues/61956
197    Ok(unsafe { core::mem::transmute_copy::<_, [T; N]>(&arr) })
198}
199
200/// Writer that writes into a `&mut [u8]` while checking the length of the buffer
201struct BufWriter<'a> {
202    bytes: &'a mut [u8],
203    offset: usize,
204}
205
206impl<'a> BufWriter<'a> {
207    fn new(bytes: &'a mut [u8]) -> Self {
208        BufWriter { bytes, offset: 0 }
209    }
210
211    fn into_str(self) -> &'a str {
212        let slice = &self.bytes[..self.offset];
213        core::str::from_utf8(slice)
214            .unwrap_or("Failed to extract valid string from BufWriter. This should never happen.")
215    }
216}
217
218impl core::fmt::Write for BufWriter<'_> {
219    fn write_str(&mut self, s: &str) -> fmt::Result {
220        if s.len() > self.bytes.len() - self.offset {
221            Err(fmt::Error)
222        } else {
223            self.bytes[self.offset..self.offset + s.len()].copy_from_slice(s.as_bytes());
224            self.offset += s.len();
225            Ok(())
226        }
227    }
228}
229
230// 58 chars is long enough for any i128 and u128 value
231pub(crate) fn get_unexpected_i128(value: i128, buf: &mut [u8; 58]) -> Unexpected<'_> {
232    let mut writer = BufWriter::new(buf);
233    fmt::Write::write_fmt(&mut writer, format_args!("integer `{value}` as i128")).unwrap();
234    Unexpected::Other(writer.into_str())
235}
236
237// 58 chars is long enough for any i128 and u128 value
238pub(crate) fn get_unexpected_u128(value: u128, buf: &mut [u8; 58]) -> Unexpected<'_> {
239    let mut writer = BufWriter::new(buf);
240    fmt::Write::write_fmt(&mut writer, format_args!("integer `{value}` as u128")).unwrap();
241    Unexpected::Other(writer.into_str())
242}