Skip to main content

deser_core/adapters/
text.rs

1//! Adapters that work on the text of values: [`Separated`],
2//! [`TrimWhitespace`] and [`SkipBlank`].
3use alloc::borrow::Cow;
4use alloc::collections::{BTreeSet, VecDeque};
5use alloc::format;
6use alloc::string::String;
7use alloc::string::ToString;
8use alloc::vec::Vec;
9#[cfg(feature = "std")]
10use core::hash::{BuildHasher, Hash};
11use core::marker::PhantomData;
12#[cfg(feature = "std")]
13use std::collections::HashSet;
14
15use crate::State;
16use crate::Text;
17use crate::adapted::{self, Adapted};
18use crate::adapters::Same;
19use crate::de::{Deserialize, Sink, SinkHandle};
20use crate::error::{Error, ErrorKind};
21use crate::event::{Atom, ContainerShape};
22use crate::ext::Number;
23use crate::ser::{Begin, Describe, Emit, Serialize};
24
25/// A sequence that is written as text with a separator, like `a,b,c`.
26///
27/// This is for lists in places where only text fits, like environment
28/// variables and command line arguments.  When deserializing, a string (or
29/// a [lexical atom](Atom::Lexical)) is split at the separator `SEP` (a comma
30/// by default) and every piece is deserialized with the adapter `A` (by
31/// default [`Same`]) as a lexical atom, so numbers and booleans parse.  The
32/// empty string is an empty sequence.  Sequences are accepted as they are
33/// (their elements are not split), so the same type still reads arrays from
34/// JSON or TOML.  Pieces are not trimmed and there is no escaping, see
35/// [`TrimWhitespace`] to trim them.
36///
37/// When serializing, the elements are joined with the separator into a
38/// string in all formats.  Elements have to be strings, numbers, booleans
39/// or chars.  Values that would not read back are an error: an element that
40/// contains the separator and a sequence of a single empty string (which
41/// would read back as the empty sequence).
42///
43/// Supported are `Vec<T>`, `VecDeque<T>`, `BTreeSet<T>` and `HashSet<T>`.
44///
45/// ```
46/// use deser::adapters::{Separated, TrimWhitespace};
47/// use deser::{Deserialize, Serialize};
48///
49/// #[derive(Serialize, Deserialize)]
50/// pub struct Config {
51///     // `a,b,c`
52///     #[deser(as = Separated)]
53///     hosts: Vec<String>,
54///     // `/usr/bin:/bin`
55///     #[deser(as = Separated<':'>)]
56///     search_path: Vec<String>,
57///     // `80, 443`
58///     #[deser(as = Separated<',', TrimWhitespace>)]
59///     ports: Vec<u16>,
60/// }
61/// ```
62pub struct Separated<const SEP: char = ',', A = Same>(PhantomData<fn() -> A>);
63
64/// Trims whitespace from the start and end of strings.
65///
66/// Strings and [lexical atoms](Atom::Lexical) are trimmed before they are
67/// deserialized with the adapter `A` (by default [`Same`]), so `" 42 "`
68/// deserializes into a number.  What is whitespace is defined by
69/// [`str::trim`].  Other values are passed on as they are.  Serialization
70/// uses the inner adapter, values are not trimmed.
71///
72/// It's typically combined with [`Separated`] to trim the pieces of a list
73/// (`Separated<',', TrimWhitespace>` reads `a, b` as `["a", "b"]`) or used on
74/// its own for values that are typed by hand.
75///
76/// Optionals are `None` for empty values if the type does not accept them
77/// (see [`Atom::Lexical`]), which is decided before the value reaches the
78/// adapters in the option.  To make blank values `None`, trim outside of
79/// the option (`TrimWhitespace<Option<_>>`):
80///
81/// ```
82/// use deser::adapters::TrimWhitespace;
83/// use deser::Deserialize;
84///
85/// #[derive(Deserialize)]
86/// pub struct Login {
87///     #[deser(as = TrimWhitespace)]
88///     username: String,
89///     // `" 80 "` is `Some(80)` and `" "` is `None`
90///     #[deser(as = TrimWhitespace<Option<_>>)]
91///     port: Option<u16>,
92/// }
93/// ```
94pub struct TrimWhitespace<A = Same>(PhantomData<fn() -> A>);
95
96/// Leaves no value for blank strings.
97///
98/// Strings and [lexical atoms](Atom::Lexical) that are empty or only
99/// whitespace (as defined by [`str::trim`]) are skipped: they leave the
100/// slot as it is.  Everything else is deserialized with the adapter `A`
101/// (by default [`Same`]).  Serialization uses the inner adapter.
102///
103/// Sequences and collections leave out elements without a value, which
104/// makes this an adapter for their elements: `Vec<SkipBlank>` drops the
105/// blank elements, in sequences as well as for keys that are given more
106/// than once (like `tag=&tag=a` in a query string or the whitespace between
107/// elements in XML).  It can be combined with [`TrimWhitespace`] (which
108/// trims the other values) and [`Separated`]:
109///
110/// ```
111/// use deser::adapters::{Separated, SkipBlank, TrimWhitespace};
112/// use deser::Deserialize;
113///
114/// #[derive(Deserialize)]
115/// pub struct Config {
116///     // `a, ,b,` is `["a", "b"]`
117///     #[deser(as = Separated<',', SkipBlank<TrimWhitespace>>)]
118///     hosts: Vec<String>,
119///     // blank values are missing, which is `None`
120///     #[deser(as = SkipBlank<Option<_>>)]
121///     name: Option<String>,
122/// }
123/// ```
124///
125/// For values that are not elements a blank string is a missing value: an
126/// optional is `None`, other types report the missing field (unless they
127/// have a default).
128pub struct SkipBlank<A = Same>(PhantomData<fn() -> A>);
129
130/// What a [`TextSink`] does with the text it receives.
131#[derive(Clone, Copy)]
132enum TextOp {
133    /// Splits the text into a sequence.
134    Split(char),
135    /// Trims the text.
136    Trim,
137}
138
139/// Changes the strings and lexical atoms a sink receives.
140///
141/// Everything else is forwarded to the inner sink.
142struct TextSink<'a, 'de> {
143    inner: SinkHandle<'a, 'de>,
144    op: TextOp,
145}
146
147impl<'a, 'de> TextSink<'a, 'de> {
148    fn handle(inner: SinkHandle<'a, 'de>, op: TextOp, state: &mut State) -> SinkHandle<'a, 'de> {
149        SinkHandle::arena(TextSink { inner, op }, state)
150    }
151}
152
153/// Returns the range of the text without the surrounding whitespace.
154fn trimmed_range(text: &str) -> (usize, usize) {
155    let start = text.len() - text.trim_start().len();
156    let end = text.trim_end().len().max(start);
157    (start, end)
158}
159
160/// Replaces the text of a string or lexical atom.
161fn with_text<'x>(atom: &Atom<'_>, text: Text<'x>) -> Atom<'x> {
162    match atom {
163        Atom::Str(_) => Atom::Str(text),
164        _ => Atom::Lexical(text),
165    }
166}
167
168/// Trims a string or lexical atom, other atoms are returned as they are.
169fn trim_atom(atom: Atom<'_>) -> Atom<'_> {
170    match atom {
171        Atom::Str(ref text) | Atom::Lexical(ref text) => {
172            let (start, end) = trimmed_range(text);
173            if start == 0 && end == text.len() {
174                return atom;
175            }
176            let trimmed = match text.borrowed_str() {
177                Some(text) => Text::borrowed(&text[start..end]),
178                None => Text::owned(&text[start..end]),
179            };
180            with_text(&atom, trimmed)
181        }
182        atom => atom,
183    }
184}
185
186/// Splits text into the elements of the sequence of a sink.
187///
188/// Invokes [`Sink::seq`] and passes the pieces on as elements, the driver
189/// invokes [`Sink::finish`] as for every atom.  Like the driver does for
190/// the elements of sequences, the sink can recover from the error of an
191/// element (see [`Sink::recover`]).
192fn split_into<'de>(
193    sink: &mut SinkHandle<'_, 'de>,
194    text: &str,
195    sep: char,
196    state: &mut State,
197) -> Result<(), Error> {
198    sink.seq(state)?;
199    if !text.is_empty() {
200        for piece in text.split(sep) {
201            let rv = sink.__private_value_atom(Atom::Lexical(Text::borrowed(piece)), state);
202            recover_element(sink, rv, state)?;
203        }
204    }
205    Ok(())
206}
207
208/// Lets the sink recover from the error of an element.
209#[inline]
210fn recover_element(
211    sink: &mut SinkHandle<'_, '_>,
212    rv: Result<(), Error>,
213    state: &mut State,
214) -> Result<(), Error> {
215    match rv {
216        Ok(()) => Ok(()),
217        Err(err) if state.discards_errors => Err(err),
218        Err(err) => sink.recover(state.error_in_context(err), state),
219    }
220}
221
222/// Splits borrowed text into the elements of the sequence of a sink.
223///
224/// Like [`split_into`] but the pieces are passed on borrowed.
225fn split_borrowed_into<'de>(
226    sink: &mut SinkHandle<'_, 'de>,
227    text: &'de str,
228    sep: char,
229    state: &mut State,
230) -> Result<(), Error> {
231    sink.seq(state)?;
232    if !text.is_empty() {
233        for piece in text.split(sep) {
234            let rv =
235                sink.__private_borrowed_value_atom(Atom::Lexical(Text::borrowed(piece)), state);
236            recover_element(sink, rv, state)?;
237        }
238    }
239    Ok(())
240}
241
242impl<'a, 'de> Sink<'de> for TextSink<'a, 'de> {
243    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
244        match (self.op, atom) {
245            (TextOp::Split(sep), Atom::Str(text) | Atom::Lexical(text)) => {
246                split_into(&mut self.inner, &text, sep, state)
247            }
248            (TextOp::Trim, atom) => self.inner.atom(trim_atom(atom), state),
249            (_, atom) => self.inner.atom(atom, state),
250        }
251    }
252
253    fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
254        match (self.op, atom) {
255            (TextOp::Split(sep), Atom::Str(ref text) | Atom::Lexical(ref text))
256                if text.is_borrowed() =>
257            {
258                let text = text.borrowed_str().unwrap_or_default();
259                split_borrowed_into(&mut self.inner, text, sep, state)
260            }
261            (TextOp::Split(sep), Atom::Str(text) | Atom::Lexical(text)) => {
262                split_into(&mut self.inner, &text, sep, state)
263            }
264            (TextOp::Trim, atom) => self.inner.borrowed_atom(trim_atom(atom), state),
265            (_, atom) => self.inner.borrowed_atom(atom, state),
266        }
267    }
268
269    fn map(&mut self, state: &mut State) -> Result<(), Error> {
270        self.inner.map(state)
271    }
272
273    fn seq(&mut self, state: &mut State) -> Result<(), Error> {
274        self.inner.seq(state)
275    }
276
277    fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
278        self.inner.next_key(state)
279    }
280
281    fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
282        self.inner.next_value(state)
283    }
284
285    fn __private_key_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
286        self.inner.__private_key_atom(atom, state)
287    }
288
289    fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
290        self.inner.__private_value_atom(atom, state)
291    }
292
293    fn __private_borrowed_key_atom(
294        &mut self,
295        atom: Atom<'de>,
296        state: &mut State,
297    ) -> Result<(), Error> {
298        self.inner.__private_borrowed_key_atom(atom, state)
299    }
300
301    fn __private_borrowed_value_atom(
302        &mut self,
303        atom: Atom<'de>,
304        state: &mut State,
305    ) -> Result<(), Error> {
306        self.inner.__private_borrowed_value_atom(atom, state)
307    }
308
309    fn value_for_key(
310        &mut self,
311        key: &str,
312        state: &mut State,
313    ) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
314        self.inner.value_for_key(key, state)
315    }
316
317    fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
318        self.inner.recover(err, state)
319    }
320
321    fn finish(&mut self, state: &mut State) -> Result<(), Error> {
322        self.inner.finish(state)
323    }
324
325    fn expecting(&self) -> Cow<'_, str> {
326        self.inner.expecting()
327    }
328}
329
330/// Returns `true` if the atom is a blank string.
331#[inline]
332fn is_blank(atom: &Atom) -> bool {
333    matches!(atom, Atom::Str(text) | Atom::Lexical(text) if text.trim().is_empty())
334}
335
336/// The sink of [`SkipBlank`].
337///
338/// The sink of the value is only created once a value arrives that is not
339/// blank, as creating it can already set the slot (like it does for
340/// optionals).  A blank string leaves a null sink.
341enum SkipBlankSink<'a, 'de, T> {
342    Pending(&'a mut Option<T>),
343    Active(SinkHandle<'a, 'de>),
344}
345
346impl<'a, 'de, T: Send> SkipBlankSink<'a, 'de, T> {
347    /// Returns the sink of the value, creates it with the adapter `A` if
348    /// needed.
349    fn active<A: Deserialize<'de, T>>(&mut self, state: &mut State) -> &mut SinkHandle<'a, 'de> {
350        if let SkipBlankSink::Pending(..) = self
351            && let SkipBlankSink::Pending(out) =
352                core::mem::replace(self, SkipBlankSink::Active(SinkHandle::null()))
353        {
354            *self = SkipBlankSink::Active(A::deserialize_into(out, state));
355        }
356        match self {
357            SkipBlankSink::Active(sink) => sink,
358            SkipBlankSink::Pending(..) => unreachable!(),
359        }
360    }
361
362    /// Skips the atom if it's blank and the first event.
363    fn skip(&mut self, atom: &Atom) -> bool {
364        if matches!(self, SkipBlankSink::Pending(..)) && is_blank(atom) {
365            *self = SkipBlankSink::Active(SinkHandle::null());
366            return true;
367        }
368        false
369    }
370}
371
372impl<'a, 'de, T: Send, A: Deserialize<'de, T>> Sink<'de> for Adapted<A, SkipBlankSink<'a, 'de, T>> {
373    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
374        if self.skip(&atom) {
375            return Ok(());
376        }
377        self.active::<A>(state).atom(atom, state)
378    }
379
380    fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
381        if self.skip(&atom) {
382            return Ok(());
383        }
384        self.active::<A>(state).borrowed_atom(atom, state)
385    }
386
387    fn map(&mut self, state: &mut State) -> Result<(), Error> {
388        self.active::<A>(state).map(state)
389    }
390
391    fn seq(&mut self, state: &mut State) -> Result<(), Error> {
392        self.active::<A>(state).seq(state)
393    }
394
395    fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
396        self.active::<A>(state).next_key(state)
397    }
398
399    fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
400        self.active::<A>(state).next_value(state)
401    }
402
403    fn __private_key_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
404        self.active::<A>(state).__private_key_atom(atom, state)
405    }
406
407    fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
408        self.active::<A>(state).__private_value_atom(atom, state)
409    }
410
411    fn __private_borrowed_key_atom(
412        &mut self,
413        atom: Atom<'de>,
414        state: &mut State,
415    ) -> Result<(), Error> {
416        self.active::<A>(state)
417            .__private_borrowed_key_atom(atom, state)
418    }
419
420    fn __private_borrowed_value_atom(
421        &mut self,
422        atom: Atom<'de>,
423        state: &mut State,
424    ) -> Result<(), Error> {
425        self.active::<A>(state)
426            .__private_borrowed_value_atom(atom, state)
427    }
428
429    fn value_for_key(
430        &mut self,
431        key: &str,
432        state: &mut State,
433    ) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
434        self.active::<A>(state).value_for_key(key, state)
435    }
436
437    fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
438        self.active::<A>(state).recover(err, state)
439    }
440
441    fn finish(&mut self, state: &mut State) -> Result<(), Error> {
442        self.active::<A>(state).finish(state)
443    }
444
445    fn expecting(&self) -> Cow<'_, str> {
446        match &**self {
447            SkipBlankSink::Active(sink) => sink.expecting(),
448            // the sink of the value does not exist yet
449            SkipBlankSink::Pending(..) => A::expecting(),
450        }
451    }
452}
453
454impl<'de, T: Send, A: Deserialize<'de, T>> Deserialize<'de, T> for SkipBlank<A> {
455    fn deserialize_into<'out>(
456        out: &'out mut Option<T>,
457        state: &mut State,
458    ) -> SinkHandle<'out, 'de> {
459        adapted::arena_sink::<A, _>(SkipBlankSink::Pending(out), state)
460    }
461
462    fn expecting() -> Cow<'static, str> {
463        A::expecting()
464    }
465
466    fn describe_type(d: &mut dyn Describe) {
467        A::describe_type(d)
468    }
469
470    fn initial_value() -> Option<T> {
471        A::initial_value()
472    }
473
474    #[inline]
475    fn __private_atom_into(
476        out: &mut Option<T>,
477        atom: Atom,
478        state: &mut State,
479    ) -> Result<(), Error> {
480        if is_blank(&atom) {
481            return Ok(());
482        }
483        A::__private_atom_into(out, atom, state)
484    }
485
486    #[inline]
487    fn __private_borrowed_atom_into(
488        out: &mut Option<T>,
489        atom: Atom<'de>,
490        state: &mut State,
491    ) -> Result<(), Error> {
492        if is_blank(&atom) {
493            return Ok(());
494        }
495        A::__private_borrowed_atom_into(out, atom, state)
496    }
497
498    fn __private_is_bytes() -> bool {
499        A::__private_is_bytes()
500    }
501
502    fn __private_vec_from_bytes(bytes: Vec<u8>) -> Option<Vec<T>> {
503        A::__private_vec_from_bytes(bytes)
504    }
505
506    fn __private_array_from_bytes<const N: usize>(bytes: &[u8]) -> Option<[T; N]> {
507        A::__private_array_from_bytes::<N>(bytes)
508    }
509}
510
511impl<'de, T: Send, A: Deserialize<'de, T>> Deserialize<'de, T> for TrimWhitespace<A> {
512    fn deserialize_into<'out>(
513        out: &'out mut Option<T>,
514        state: &mut State,
515    ) -> SinkHandle<'out, 'de> {
516        TextSink::handle(A::deserialize_into(out, state), TextOp::Trim, state)
517    }
518
519    fn expecting() -> Cow<'static, str> {
520        A::expecting()
521    }
522
523    fn describe_type(d: &mut dyn Describe) {
524        A::describe_type(d)
525    }
526
527    fn initial_value() -> Option<T> {
528        A::initial_value()
529    }
530
531    #[inline]
532    fn __private_atom_into(
533        out: &mut Option<T>,
534        atom: Atom,
535        state: &mut State,
536    ) -> Result<(), Error> {
537        A::__private_atom_into(out, trim_atom(atom), state)
538    }
539
540    #[inline]
541    fn __private_borrowed_atom_into(
542        out: &mut Option<T>,
543        atom: Atom<'de>,
544        state: &mut State,
545    ) -> Result<(), Error> {
546        A::__private_borrowed_atom_into(out, trim_atom(atom), state)
547    }
548
549    fn __private_is_bytes() -> bool {
550        A::__private_is_bytes()
551    }
552
553    fn __private_vec_from_bytes(bytes: Vec<u8>) -> Option<Vec<T>> {
554        A::__private_vec_from_bytes(bytes)
555    }
556
557    fn __private_array_from_bytes<const N: usize>(bytes: &[u8]) -> Option<[T; N]> {
558        A::__private_array_from_bytes::<N>(bytes)
559    }
560}
561
562impl<T: ?Sized, A: Serialize<T>> Serialize<T> for TrimWhitespace<A> {
563    fn serialize<'a>(value: &'a T, state: &mut State) -> Result<Emit<'a>, Error> {
564        A::serialize(value, state)
565    }
566
567    fn finish(value: &T, state: &mut State) -> Result<(), Error> {
568        A::finish(value, state)
569    }
570
571    fn is_optional(value: &T) -> bool {
572        A::is_optional(value)
573    }
574
575    fn container_shape(value: &T) -> ContainerShape {
576        A::container_shape(value)
577    }
578
579    fn describe(value: &T, d: &mut dyn Describe) {
580        A::describe(value, d)
581    }
582
583    #[inline]
584    fn __private_begin<'a>(value: &'a T, state: &mut State) -> Result<Begin<'a>, Error> {
585        A::__private_begin(value, state)
586    }
587
588    fn __private_slice_as_bytes(val: &[T]) -> Option<Cow<'_, [u8]>>
589    where
590        T: Sized,
591    {
592        A::__private_slice_as_bytes(val)
593    }
594}
595
596impl<T: ?Sized, A: Serialize<T>> Serialize<T> for SkipBlank<A> {
597    fn serialize<'a>(value: &'a T, state: &mut State) -> Result<Emit<'a>, Error> {
598        A::serialize(value, state)
599    }
600
601    fn finish(value: &T, state: &mut State) -> Result<(), Error> {
602        A::finish(value, state)
603    }
604
605    fn is_optional(value: &T) -> bool {
606        A::is_optional(value)
607    }
608
609    fn container_shape(value: &T) -> ContainerShape {
610        A::container_shape(value)
611    }
612
613    fn describe(value: &T, d: &mut dyn Describe) {
614        A::describe(value, d)
615    }
616
617    #[inline]
618    fn __private_begin<'a>(value: &'a T, state: &mut State) -> Result<Begin<'a>, Error> {
619        A::__private_begin(value, state)
620    }
621
622    fn __private_slice_as_bytes(val: &[T]) -> Option<Cow<'_, [u8]>>
623    where
624        T: Sized,
625    {
626        A::__private_slice_as_bytes(val)
627    }
628}
629
630#[cold]
631fn unsupported_element(what: &str) -> Error {
632    Error::new(
633        ErrorKind::UnsupportedType,
634        format!(
635            "cannot join {}, elements must be strings, numbers, booleans or chars",
636            what
637        ),
638    )
639}
640
641/// Returns the text of an element.
642fn atom_text<'a>(atom: &'a Atom<'_>) -> Result<Cow<'a, str>, Error> {
643    Ok(match *atom {
644        Atom::Bool(value) => Cow::Borrowed(if value { "true" } else { "false" }),
645        Atom::Str(ref value) | Atom::Lexical(ref value) => Cow::Borrowed(value),
646        Atom::Char(value) => Cow::Owned(value.to_string()),
647        Atom::U64(value) => Cow::Owned(value.to_string()),
648        Atom::I64(value) => Cow::Owned(value.to_string()),
649        Atom::F32(value) => Cow::Owned(value.to_string()),
650        Atom::F64(value) => Cow::Owned(value.to_string()),
651        Atom::Ext(ref ext) => {
652            if let Some(number) = ext.downcast_value_ref::<Number>() {
653                // numbers keep their text
654                Cow::Owned(number.as_str().to_string())
655            } else if let Some(value) = ext.downcast_ref::<u128>() {
656                Cow::Owned(value.to_string())
657            } else if let Some(value) = ext.downcast_ref::<i128>() {
658                Cow::Owned(value.to_string())
659            } else {
660                match ext.fallback() {
661                    Atom::Ext(_) => return Err(unsupported_element(ext.name())),
662                    fallback => Cow::Owned(atom_text(&fallback)?.into_owned()),
663                }
664            }
665        }
666        ref atom => return Err(unsupported_element(atom.name())),
667    })
668}
669
670/// Appends the text of a serialized element.
671fn push_emit(emit: Emit<'_>, state: &mut State, out: &mut String) -> Result<(), Error> {
672    match emit {
673        Emit::Atom(ref atom) => out.push_str(&atom_text(atom)?),
674        Emit::Forward(handle) => {
675            push_emit(handle.get().serialize(state)?, state, out)?;
676            handle.get().finish(state)?;
677        }
678        Emit::Struct(_) | Emit::Map(_) => return Err(unsupported_element("map")),
679        Emit::Seq(_) => return Err(unsupported_element("sequence")),
680    }
681    Ok(())
682}
683
684/// Joins the elements of a sequence into a string.
685fn join<'v, T: 'v, A: Serialize<T>>(
686    values: impl Iterator<Item = &'v T>,
687    sep: char,
688    state: &mut State,
689) -> Result<String, Error> {
690    let mut out = String::new();
691    let mut count = 0;
692    for value in values {
693        if count > 0 {
694            out.push(sep);
695        }
696        count += 1;
697        let start = out.len();
698        push_emit(A::serialize(value, state)?, state, &mut out)?;
699        A::finish(value, state)?;
700        if out[start..].contains(sep) {
701            return Err(Error::new(
702                ErrorKind::InvalidValue,
703                format!(
704                    "cannot join {:?}, it contains the separator {:?}",
705                    &out[start..],
706                    sep
707                ),
708            ));
709        }
710    }
711    if count == 1 && out.is_empty() {
712        return Err(Error::new(
713            ErrorKind::InvalidValue,
714            "cannot join a single empty string, it would read back as no elements",
715        ));
716    }
717    Ok(out)
718}
719
720/// Implements `Separated` for sequences.
721macro_rules! separated_impls {
722    ($([$($bound:tt)*] [$($ser_bound:tt)*] $target:ty => $adapter:ty;)*) => {
723        $(
724            impl<'de, $($bound)*, A: Deserialize<'de, T>, const SEP: char>
725                Deserialize<'de, $target> for Separated<SEP, A>
726            {
727                fn deserialize_into<'out>(out: &'out mut Option<$target>, state: &mut State) -> SinkHandle<'out, 'de> {
728                    TextSink::handle(
729                        <$adapter as Deserialize<'de, $target>>::deserialize_into(out, state),
730                        TextOp::Split(SEP), state)
731                }
732
733                fn expecting() -> Cow<'static, str> {
734                    <$adapter as Deserialize<'de, $target>>::expecting()
735                }
736            }
737
738            impl<$($ser_bound)*, A: Serialize<T>, const SEP: char> Serialize<$target>
739                for Separated<SEP, A>
740            {
741                fn serialize<'a>(
742                    value: &'a $target,
743                    state: &mut State,
744                ) -> Result<Emit<'a>, Error> {
745                    let text = join::<T, A>(value.iter(), SEP, state)?;
746                    Ok(Emit::Atom(Atom::Str(Text::owned(text))))
747                }
748
749                #[inline]
750                fn __private_begin<'a>(
751                    value: &'a $target,
752                    state: &mut State,
753                ) -> Result<Begin<'a>, Error> {
754                    Ok(Begin::emit(
755                        Self::serialize(value, state)?,
756                        ContainerShape::new(),
757                        false,
758                    ))
759                }
760            }
761        )*
762    };
763}
764
765separated_impls! {
766    [T: Send] [T] Vec<T> => Vec<A>;
767    [T: Send] [T] VecDeque<T> => VecDeque<A>;
768    [T: Ord + Send] [T] BTreeSet<T> => BTreeSet<A>;
769}
770
771#[cfg(feature = "std")]
772separated_impls! {
773    [T: Hash + Eq + Send, H: BuildHasher + Default + Send] [T, H] HashSet<T, H> => HashSet<A>;
774}