Skip to main content

deser_core/foreign_impls/
arrayvec.rs

1//! `ArrayVec` and `ArrayString` of `arrayvec`.
2//!
3//! `ArrayVec` is serialized like `Vec`: `ArrayVec<u8, CAP>` as bytes,
4//! everything else as sequence.  `ArrayString` is serialized like `String`.
5//! Deserializing more elements or a longer string than the capacity is an
6//! error.
7use alloc::borrow::Cow;
8use alloc::format;
9use alloc::vec::Vec;
10
11use ::arrayvec::{ArrayString, ArrayVec};
12
13use crate::State;
14use crate::Text;
15use crate::adapters::bytes::{BytesBufImpl, encoding_adapter};
16use crate::de::impls::{SeqTarget, collection_methods, seq_expecting, seq_sink};
17use crate::de::update::Collection;
18use crate::de::{Deserialize, SinkHandle, Slot, default_atom};
19use crate::error::{Error, ErrorKind};
20use crate::event::Atom;
21use crate::ser::impls::serialize_slice;
22use crate::ser::{Emit, Serialize, plain_atom};
23
24serialize_slice! {
25    [T: Sync, A: Serialize<T>, const CAP: usize] ArrayVec<T, CAP> => ArrayVec<A, CAP>, A;
26}
27
28/// Creates the error for values that exceed the capacity.
29#[cold]
30fn capacity_exceeded(what: &str, capacity: usize) -> Error {
31    Error::new(
32        ErrorKind::WrongLength,
33        format!("{what} exceeds the capacity of {capacity}"),
34    )
35}
36
37/// Converts a vector into an `ArrayVec`.
38fn array_vec_from_vec<T, const CAP: usize>(vec: Vec<T>) -> Result<ArrayVec<T, CAP>, Error> {
39    if vec.len() > CAP {
40        return Err(capacity_exceeded("ArrayVec", CAP));
41    }
42    let mut rv = ArrayVec::new();
43    rv.extend(vec);
44    Ok(rv)
45}
46
47impl<T: Send, const CAP: usize> SeqTarget<T> for ArrayVec<T, CAP> {
48    const NAME: &'static str = "ArrayVec";
49
50    #[inline]
51    fn from_vec(vec: Vec<T>) -> Result<Self, Error> {
52        array_vec_from_vec(vec)
53    }
54}
55
56impl<'de, T: Send, A: Deserialize<'de, T>, const CAP: usize> Deserialize<'de, ArrayVec<T, CAP>>
57    for ArrayVec<A, CAP>
58{
59    fn deserialize_into<'out>(
60        out: &'out mut Option<ArrayVec<T, CAP>>,
61        state: &mut State,
62    ) -> SinkHandle<'out, 'de> {
63        seq_sink::<ArrayVec<T, CAP>, T, A>(out, state)
64    }
65
66    fn expecting() -> Cow<'static, str> {
67        seq_expecting::<ArrayVec<T, CAP>, T, A>()
68    }
69
70    collection_methods!(ArrayVec<T, CAP>);
71}
72
73impl<T: Send, const CAP: usize> Collection<T> for ArrayVec<T, CAP> {
74    fn empty() -> Self {
75        ArrayVec::new()
76    }
77
78    fn add(&mut self, value: T) -> Result<(), Error> {
79        self.try_push(value)
80            .map_err(|_| capacity_exceeded("ArrayVec", CAP))
81    }
82}
83
84impl<const CAP: usize> BytesBufImpl for ArrayVec<u8, CAP> {
85    #[inline]
86    fn bytes(&self) -> &[u8] {
87        self
88    }
89
90    #[inline]
91    fn from_vec(bytes: Vec<u8>) -> Result<Self, Error> {
92        array_vec_from_vec(bytes)
93    }
94
95    #[inline]
96    fn deserialize_into<'a, 'de>(
97        out: &'a mut Option<Self>,
98        state: &mut State,
99    ) -> SinkHandle<'a, 'de> {
100        <Self as Deserialize<'de>>::deserialize_into(out, state)
101    }
102
103    fn expecting() -> Cow<'static, str> {
104        <Self as Deserialize<'static>>::expecting()
105    }
106}
107
108encoding_adapter!(
109    [const CAP: usize,] ArrayVec<u8, CAP>,
110);
111
112impl<const CAP: usize> Serialize for ArrayString<CAP> {
113    begin_without_finish!();
114    plain_atom!(|v| Atom::Str(Text::borrowed(v.as_str())));
115
116    fn serialize<'a>(value: &'a Self, _state: &mut State) -> Result<Emit<'a>, Error> {
117        Ok(Emit::Atom(Atom::Str(Text::borrowed(value.as_str()))))
118    }
119}
120
121impl<'de, const CAP: usize> Deserialize<'de> for ArrayString<CAP> {
122    fn deserialize_atom(slot: &mut Slot<Self>, atom: Atom, state: &mut State) -> Result<(), Error> {
123        let mut rv = ArrayString::new();
124        match atom {
125            Atom::Str(ref value) | Atom::Lexical(ref value) => rv
126                .try_push_str(value)
127                .map_err(|_| capacity_exceeded("string", CAP))?,
128            Atom::Char(value) => rv
129                .try_push(value)
130                .map_err(|_| capacity_exceeded("string", CAP))?,
131            other => return default_atom(slot, other, state),
132        }
133        slot.set(rv);
134        Ok(())
135    }
136
137    fn expecting() -> Cow<'static, str> {
138        Cow::Borrowed("string")
139    }
140
141    slot_atom_into!();
142}