Skip to main content

deser_core/foreign_impls/
bstr.rs

1//! `BString` and `BStr` of `bstr`.
2//!
3//! Byte strings are conventionally UTF-8.  They are serialized as strings if
4//! they are valid UTF-8 and as bytes otherwise.  The bytes carry sequences
5//! of integers as fallback (see [`BytesFormat::SEQ`]) so that formats
6//! without native bytes (like JSON) can tell them apart from strings.
7//!
8//! When deserialized, strings are taken as their UTF-8 bytes (like the
9//! serde implementation of `bstr`).  Besides strings, byte strings accept
10//! bytes and sequences of integers.  `&BStr` borrows strings and bytes from
11//! the data.
12use alloc::borrow::Cow;
13use alloc::boxed::Box;
14use alloc::string::ToString;
15use alloc::vec::Vec;
16use core::mem::take;
17
18use ::bstr::{BStr, BString};
19
20use crate::BytesFormat;
21use crate::State;
22use crate::Text;
23use crate::adapters::bytes::{BytesBufImpl, encoding_adapter};
24use crate::de::impls::{Via, deserialize_via};
25use crate::de::{Deserialize, Sink, SinkHandle};
26use crate::error::{Error, ErrorKind};
27use crate::event::{Atom, Bytes};
28use crate::ser::{Chunk, Serialize, plain_atom};
29
30make_slot_wrapper!(SlotWrapper);
31
32/// Returns the atom of a byte string.
33#[inline]
34fn bstr_atom(bytes: &[u8]) -> Atom<'_> {
35    match core::str::from_utf8(bytes) {
36        Ok(value) => Atom::Str(Text::borrowed(value)),
37        Err(_) => Atom::Bytes(Bytes::borrowed(bytes).with_fallback(const { &BytesFormat::SEQ })),
38    }
39}
40
41impl Serialize for BStr {
42    begin_without_finish!();
43
44    fn serialize(&self, _state: &mut State) -> Result<Chunk<'_>, Error> {
45        Ok(Chunk::Atom(bstr_atom(self)))
46    }
47}
48
49impl Serialize for BString {
50    begin_without_finish!();
51    plain_atom!(|v| bstr_atom(v));
52
53    fn serialize(&self, _state: &mut State) -> Result<Chunk<'_>, Error> {
54        Ok(Chunk::Atom(bstr_atom(self)))
55    }
56}
57
58/// Converts an atom into a byte string.
59///
60/// Returns the atom back if it's not a string or bytes.
61#[inline]
62fn bstring_from_atom(atom: Atom) -> Result<BString, Atom> {
63    match atom {
64        Atom::Str(value) | Atom::Lexical(value) => Ok(BString::from(value.into_owned())),
65        Atom::Char(value) => Ok(BString::from(value.to_string())),
66        Atom::Bytes(value) => Ok(BString::from(value.into_owned())),
67        other => Err(other),
68    }
69}
70
71/// Deserializes byte strings from strings, bytes and sequences of integers.
72struct BStringSink<'a> {
73    out: &'a mut Option<BString>,
74    bytes: Vec<u8>,
75    element: Option<u8>,
76    is_seq: bool,
77}
78
79impl BStringSink<'_> {
80    #[inline]
81    fn flush(&mut self) {
82        if let Some(byte) = self.element.take() {
83            self.bytes.push(byte);
84        }
85    }
86}
87
88impl<'de> Sink<'de> for BStringSink<'_> {
89    fn expecting(&self) -> Cow<'_, str> {
90        Cow::Borrowed("byte string")
91    }
92
93    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
94        match bstring_from_atom(atom) {
95            Ok(value) => {
96                *self.out = Some(value);
97                Ok(())
98            }
99            Err(other) => self.unexpected_atom(other, state),
100        }
101    }
102
103    fn seq(&mut self, _state: &mut State) -> Result<(), Error> {
104        self.is_seq = true;
105        Ok(())
106    }
107
108    fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
109        self.flush();
110        Ok(u8::deserialize_into(&mut self.element, state))
111    }
112
113    fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
114        self.flush();
115        u8::__private_atom_into(&mut self.element, atom, state)
116    }
117
118    fn finish(&mut self, _state: &mut State) -> Result<(), Error> {
119        if self.is_seq {
120            self.flush();
121            *self.out = Some(BString::from(take(&mut self.bytes)));
122        }
123        Ok(())
124    }
125}
126
127impl<'de> Deserialize<'de> for BString {
128    fn deserialize_into<'out>(
129        out: &'out mut Option<Self>,
130        state: &mut State,
131    ) -> SinkHandle<'out, 'de> {
132        SinkHandle::arena(
133            BStringSink {
134                out,
135                bytes: Vec::new(),
136                element: None,
137                is_seq: false,
138            },
139            state,
140        )
141    }
142
143    #[inline]
144    fn __private_atom_into(
145        out: &mut Option<Self>,
146        atom: Atom,
147        state: &mut State,
148    ) -> Result<(), Error> {
149        match bstring_from_atom(atom) {
150            Ok(value) => {
151                *out = Some(value);
152                Ok(())
153            }
154            Err(other) => {
155                let mut sink = BStringSink {
156                    out,
157                    bytes: Vec::new(),
158                    element: None,
159                    is_seq: false,
160                };
161                sink.atom(other, state)
162            }
163        }
164    }
165
166    #[inline]
167    fn __private_borrowed_atom_into(
168        out: &mut Option<Self>,
169        atom: Atom<'de>,
170        state: &mut State,
171    ) -> Result<(), Error> {
172        // the sink does not borrow
173        Self::__private_atom_into(out, atom, state)
174    }
175}
176
177impl Via<BString> for Box<BStr> {
178    #[inline]
179    fn convert(value: BString) -> Result<Self, Error> {
180        Ok(Box::from(Vec::from(value).into_boxed_slice()))
181    }
182}
183
184deserialize_via! {
185    [] Box<BStr> => BString;
186}
187
188/// The bytes adapters represent the raw bytes, not the string.
189impl BytesBufImpl for BString {
190    #[inline]
191    fn bytes(&self) -> &[u8] {
192        self.as_slice()
193    }
194
195    #[inline]
196    fn from_vec(bytes: Vec<u8>) -> Result<Self, Error> {
197        Ok(BString::from(bytes))
198    }
199
200    #[inline]
201    fn deserialize_into<'a, 'de>(
202        out: &'a mut Option<Self>,
203        state: &mut State,
204    ) -> SinkHandle<'a, 'de> {
205        Deserialize::deserialize_into(out, state)
206    }
207}
208
209encoding_adapter!([] BString);
210
211impl<'de: 'a, 'a> Sink<'de> for SlotWrapper<&'a BStr> {
212    fn expecting(&self) -> Cow<'_, str> {
213        Cow::Borrowed("borrowed byte string")
214    }
215
216    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
217        match atom {
218            Atom::Str(_) | Atom::Lexical(_) | Atom::Bytes(_) => Err(Error::new(
219                ErrorKind::Unexpected,
220                "unexpected owned byte string, expected a borrowed byte string (the data \
221                 format or the type buffering the value does not support borrowing)",
222            )),
223            other => self.unexpected_atom(other, state),
224        }
225    }
226
227    fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
228        match atom {
229            Atom::Str(ref text) | Atom::Lexical(ref text) if text.is_borrowed() => {
230                **self = text.borrowed_str().map(BStr::new);
231                Ok(())
232            }
233            Atom::Implicit(ref value) if value.text().is_borrowed() => {
234                **self = value.text().borrowed_str().map(BStr::new);
235                Ok(())
236            }
237            Atom::Bytes(ref value) if value.is_borrowed() => {
238                **self = value.borrowed_data().map(BStr::new);
239                Ok(())
240            }
241            other => self.atom(other, state),
242        }
243    }
244}
245
246/// Borrows strings and bytes from the data.
247impl<'de: 'a, 'a> Deserialize<'de> for &'a BStr {
248    fn deserialize_into<'out>(
249        out: &'out mut Option<Self>,
250        _state: &mut State,
251    ) -> SinkHandle<'out, 'de> {
252        SlotWrapper::make_handle(out)
253    }
254}