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::adapters::Same;
18use crate::de::{Deserialize, Sink, SinkHandle};
19use crate::error::{Error, ErrorKind};
20use crate::event::{Atom, ContainerShape};
21use crate::ext::Number;
22use crate::ser::{Begin, Describe, Emit, Serialize};
23
24/// A sequence that is written as text with a separator, like `a,b,c`.
25///
26/// This is for lists in places where only text fits, like environment
27/// variables and command line arguments.  When deserializing, a string (or
28/// a [lexical atom](Atom::Lexical)) is split at the separator `SEP` (a comma
29/// by default) and every piece is deserialized with the adapter `A` (by
30/// default [`Same`]) as a lexical atom, so numbers and booleans parse.  The
31/// empty string is an empty sequence.  Sequences are accepted as they are
32/// (their elements are not split), so the same type still reads arrays from
33/// JSON or TOML.  Pieces are not trimmed and there is no escaping, see
34/// [`TrimWhitespace`] to trim them.
35///
36/// When serializing, the elements are joined with the separator into a
37/// string in all formats.  Elements have to be strings, numbers, booleans
38/// or chars.  Values that would not read back are an error: an element that
39/// contains the separator and a sequence of a single empty string (which
40/// would read back as the empty sequence).
41///
42/// Supported are `Vec<T>`, `VecDeque<T>`, `BTreeSet<T>` and `HashSet<T>`.
43///
44/// ```
45/// use deser::adapters::{Separated, TrimWhitespace};
46/// use deser::{Deserialize, Serialize};
47///
48/// #[derive(Serialize, Deserialize)]
49/// pub struct Config {
50///     // `a,b,c`
51///     #[deser(as = Separated)]
52///     hosts: Vec<String>,
53///     // `/usr/bin:/bin`
54///     #[deser(as = Separated<':'>)]
55///     search_path: Vec<String>,
56///     // `80, 443`
57///     #[deser(as = Separated<',', TrimWhitespace>)]
58///     ports: Vec<u16>,
59/// }
60/// ```
61pub struct Separated<const SEP: char = ',', A = Same>(PhantomData<fn() -> A>);
62
63/// Trims whitespace from the start and end of strings.
64///
65/// Strings and [lexical atoms](Atom::Lexical) are trimmed before they are
66/// deserialized with the adapter `A` (by default [`Same`]), so `" 42 "`
67/// deserializes into a number.  What is whitespace is defined by
68/// [`str::trim`].  Other values are passed on as they are.  Serialization
69/// uses the inner adapter, values are not trimmed.
70///
71/// It's typically combined with [`Separated`] to trim the pieces of a list
72/// (`Separated<',', TrimWhitespace>` reads `a, b` as `["a", "b"]`) or used on
73/// its own for values that are typed by hand.
74///
75/// Optionals are `None` for empty values if the type does not accept them
76/// (see [`Atom::Lexical`]), which is decided before the value reaches the
77/// adapters in the option.  To make blank values `None`, trim outside of
78/// the option (`TrimWhitespace<Option<_>>`):
79///
80/// ```
81/// use deser::adapters::TrimWhitespace;
82/// use deser::Deserialize;
83///
84/// #[derive(Deserialize)]
85/// pub struct Login {
86///     #[deser(as = TrimWhitespace)]
87///     username: String,
88///     // `" 80 "` is `Some(80)` and `" "` is `None`
89///     #[deser(as = TrimWhitespace<Option<_>>)]
90///     port: Option<u16>,
91/// }
92/// ```
93pub struct TrimWhitespace<A = Same>(PhantomData<fn() -> A>);
94
95/// Leaves no value for blank strings.
96///
97/// Strings and [lexical atoms](Atom::Lexical) that are empty or only
98/// whitespace (as defined by [`str::trim`]) are skipped: they leave the
99/// slot as it is.  Everything else is deserialized with the adapter `A`
100/// (by default [`Same`]).  Serialization uses the inner adapter.
101///
102/// Sequences and collections leave out elements without a value, which
103/// makes this an adapter for their elements: `Vec<SkipBlank>` drops the
104/// blank elements, in sequences as well as for keys that are given more
105/// than once (like `tag=&tag=a` in a query string or the whitespace between
106/// elements in XML).  It can be combined with [`TrimWhitespace`] (which
107/// trims the other values) and [`Separated`]:
108///
109/// ```
110/// use deser::adapters::{Separated, SkipBlank, TrimWhitespace};
111/// use deser::Deserialize;
112///
113/// #[derive(Deserialize)]
114/// pub struct Config {
115///     // `a, ,b,` is `["a", "b"]`
116///     #[deser(as = Separated<',', SkipBlank<TrimWhitespace>>)]
117///     hosts: Vec<String>,
118///     // blank values are missing, which is `None`
119///     #[deser(as = SkipBlank<Option<_>>)]
120///     name: Option<String>,
121/// }
122/// ```
123///
124/// For values that are not elements a blank string is a missing value: an
125/// optional is `None`, other types report the missing field (unless they
126/// have a default).
127pub struct SkipBlank<A = Same>(PhantomData<fn() -> A>);
128
129/// What a [`TextSink`] does with the text it receives.
130#[derive(Clone, Copy)]
131enum TextOp {
132    /// Splits the text into a sequence.
133    Split(char),
134    /// Trims the text.
135    Trim,
136}
137
138/// Changes the strings and lexical atoms a sink receives.
139///
140/// Everything else is forwarded to the inner sink.
141struct TextSink<'a, 'de> {
142    inner: SinkHandle<'a, 'de>,
143    op: TextOp,
144}
145
146impl<'a, 'de> TextSink<'a, 'de> {
147    fn handle(inner: SinkHandle<'a, 'de>, op: TextOp, state: &mut State) -> SinkHandle<'a, 'de> {
148        SinkHandle::arena(TextSink { inner, op }, state)
149    }
150}
151
152/// Returns the range of the text without the surrounding whitespace.
153fn trimmed_range(text: &str) -> (usize, usize) {
154    let start = text.len() - text.trim_start().len();
155    let end = text.trim_end().len().max(start);
156    (start, end)
157}
158
159/// Replaces the text of a string or lexical atom.
160fn with_text<'x>(atom: &Atom<'_>, text: Text<'x>) -> Atom<'x> {
161    match atom {
162        Atom::Str(_) => Atom::Str(text),
163        _ => Atom::Lexical(text),
164    }
165}
166
167/// Trims a string or lexical atom, other atoms are returned as they are.
168fn trim_atom(atom: Atom<'_>) -> Atom<'_> {
169    match atom {
170        Atom::Str(ref text) | Atom::Lexical(ref text) => {
171            let (start, end) = trimmed_range(text);
172            if start == 0 && end == text.len() {
173                return atom;
174            }
175            let trimmed = match text.borrowed_str() {
176                Some(text) => Text::borrowed(&text[start..end]),
177                None => Text::owned(&text[start..end]),
178            };
179            with_text(&atom, trimmed)
180        }
181        atom => atom,
182    }
183}
184
185/// Splits text into the elements of the sequence of a sink.
186///
187/// Invokes [`Sink::seq`] and passes the pieces on as elements, the driver
188/// invokes [`Sink::finish`] as for every atom.  Like the driver does for
189/// the elements of sequences, the sink can recover from the error of an
190/// element (see [`Sink::recover`]).
191fn split_into<'de>(
192    sink: &mut SinkHandle<'_, 'de>,
193    text: &str,
194    sep: char,
195    state: &mut State,
196) -> Result<(), Error> {
197    sink.seq(state)?;
198    if !text.is_empty() {
199        for piece in text.split(sep) {
200            let rv = sink.__private_value_atom(Atom::Lexical(Text::borrowed(piece)), state);
201            recover_element(sink, rv, state)?;
202        }
203    }
204    Ok(())
205}
206
207/// Lets the sink recover from the error of an element.
208#[inline]
209fn recover_element(
210    sink: &mut SinkHandle<'_, '_>,
211    rv: Result<(), Error>,
212    state: &mut State,
213) -> Result<(), Error> {
214    match rv {
215        Ok(()) => Ok(()),
216        Err(err) if state.discards_errors => Err(err),
217        Err(err) => sink.recover(state.error_in_context(err), state),
218    }
219}
220
221/// Splits borrowed text into the elements of the sequence of a sink.
222///
223/// Like [`split_into`] but the pieces are passed on borrowed.
224fn split_borrowed_into<'de>(
225    sink: &mut SinkHandle<'_, 'de>,
226    text: &'de str,
227    sep: char,
228    state: &mut State,
229) -> Result<(), Error> {
230    sink.seq(state)?;
231    if !text.is_empty() {
232        for piece in text.split(sep) {
233            let rv =
234                sink.__private_borrowed_value_atom(Atom::Lexical(Text::borrowed(piece)), state);
235            recover_element(sink, rv, state)?;
236        }
237    }
238    Ok(())
239}
240
241impl<'a, 'de> Sink<'de> for TextSink<'a, 'de> {
242    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
243        match (self.op, atom) {
244            (TextOp::Split(sep), Atom::Str(text) | Atom::Lexical(text)) => {
245                split_into(&mut self.inner, &text, sep, state)
246            }
247            (TextOp::Trim, atom) => self.inner.atom(trim_atom(atom), state),
248            (_, atom) => self.inner.atom(atom, state),
249        }
250    }
251
252    fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
253        match (self.op, atom) {
254            (TextOp::Split(sep), Atom::Str(ref text) | Atom::Lexical(ref text))
255                if text.is_borrowed() =>
256            {
257                let text = text.borrowed_str().unwrap_or_default();
258                split_borrowed_into(&mut self.inner, text, sep, state)
259            }
260            (TextOp::Split(sep), Atom::Str(text) | Atom::Lexical(text)) => {
261                split_into(&mut self.inner, &text, sep, state)
262            }
263            (TextOp::Trim, atom) => self.inner.borrowed_atom(trim_atom(atom), state),
264            (_, atom) => self.inner.borrowed_atom(atom, state),
265        }
266    }
267
268    fn map(&mut self, state: &mut State) -> Result<(), Error> {
269        self.inner.map(state)
270    }
271
272    fn seq(&mut self, state: &mut State) -> Result<(), Error> {
273        self.inner.seq(state)
274    }
275
276    fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
277        self.inner.next_key(state)
278    }
279
280    fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
281        self.inner.next_value(state)
282    }
283
284    fn __private_key_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
285        self.inner.__private_key_atom(atom, state)
286    }
287
288    fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
289        self.inner.__private_value_atom(atom, state)
290    }
291
292    fn __private_borrowed_key_atom(
293        &mut self,
294        atom: Atom<'de>,
295        state: &mut State,
296    ) -> Result<(), Error> {
297        self.inner.__private_borrowed_key_atom(atom, state)
298    }
299
300    fn __private_borrowed_value_atom(
301        &mut self,
302        atom: Atom<'de>,
303        state: &mut State,
304    ) -> Result<(), Error> {
305        self.inner.__private_borrowed_value_atom(atom, state)
306    }
307
308    fn value_for_key(
309        &mut self,
310        key: &str,
311        state: &mut State,
312    ) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
313        self.inner.value_for_key(key, state)
314    }
315
316    fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
317        self.inner.recover(err, state)
318    }
319
320    fn finish(&mut self, state: &mut State) -> Result<(), Error> {
321        self.inner.finish(state)
322    }
323
324    fn expecting(&self) -> Cow<'_, str> {
325        self.inner.expecting()
326    }
327}
328
329/// Returns `true` if the atom is a blank string.
330#[inline]
331fn is_blank(atom: &Atom) -> bool {
332    matches!(atom, Atom::Str(text) | Atom::Lexical(text) if text.trim().is_empty())
333}
334
335/// The sink of [`SkipBlank`].
336///
337/// The sink of the value is only created once a value arrives that is not
338/// blank, as creating it can already set the slot (like it does for
339/// optionals).  A blank string leaves a null sink.
340enum SkipBlankSink<'a, 'de, T, A> {
341    Pending(&'a mut Option<T>, PhantomData<fn() -> A>),
342    Active(SinkHandle<'a, 'de>),
343}
344
345impl<'a, 'de, T: Send, A: Deserialize<'de, T>> SkipBlankSink<'a, 'de, T, A> {
346    /// Returns the sink of the value, creates it if needed.
347    fn active(&mut self, state: &mut State) -> &mut SinkHandle<'a, 'de> {
348        if let SkipBlankSink::Pending(..) = self
349            && let SkipBlankSink::Pending(out, _) =
350                core::mem::replace(self, SkipBlankSink::Active(SinkHandle::null()))
351        {
352            *self = SkipBlankSink::Active(A::deserialize_into(out, state));
353        }
354        match self {
355            SkipBlankSink::Active(sink) => sink,
356            SkipBlankSink::Pending(..) => unreachable!(),
357        }
358    }
359
360    /// Skips the atom if it's blank and the first event.
361    fn skip(&mut self, atom: &Atom) -> bool {
362        if matches!(self, SkipBlankSink::Pending(..)) && is_blank(atom) {
363            *self = SkipBlankSink::Active(SinkHandle::null());
364            return true;
365        }
366        false
367    }
368}
369
370impl<'a, 'de, T: Send, A: Deserialize<'de, T>> Sink<'de> for SkipBlankSink<'a, 'de, T, A> {
371    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
372        if self.skip(&atom) {
373            return Ok(());
374        }
375        self.active(state).atom(atom, state)
376    }
377
378    fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
379        if self.skip(&atom) {
380            return Ok(());
381        }
382        self.active(state).borrowed_atom(atom, state)
383    }
384
385    fn map(&mut self, state: &mut State) -> Result<(), Error> {
386        self.active(state).map(state)
387    }
388
389    fn seq(&mut self, state: &mut State) -> Result<(), Error> {
390        self.active(state).seq(state)
391    }
392
393    fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
394        self.active(state).next_key(state)
395    }
396
397    fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
398        self.active(state).next_value(state)
399    }
400
401    fn __private_key_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
402        self.active(state).__private_key_atom(atom, state)
403    }
404
405    fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
406        self.active(state).__private_value_atom(atom, state)
407    }
408
409    fn __private_borrowed_key_atom(
410        &mut self,
411        atom: Atom<'de>,
412        state: &mut State,
413    ) -> Result<(), Error> {
414        self.active(state).__private_borrowed_key_atom(atom, state)
415    }
416
417    fn __private_borrowed_value_atom(
418        &mut self,
419        atom: Atom<'de>,
420        state: &mut State,
421    ) -> Result<(), Error> {
422        self.active(state)
423            .__private_borrowed_value_atom(atom, state)
424    }
425
426    fn value_for_key(
427        &mut self,
428        key: &str,
429        state: &mut State,
430    ) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
431        self.active(state).value_for_key(key, state)
432    }
433
434    fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
435        self.active(state).recover(err, state)
436    }
437
438    fn finish(&mut self, state: &mut State) -> Result<(), Error> {
439        self.active(state).finish(state)
440    }
441
442    fn expecting(&self) -> Cow<'_, str> {
443        match self {
444            SkipBlankSink::Active(sink) => sink.expecting(),
445            // the sink of the value does not exist yet
446            SkipBlankSink::Pending(..) => A::expecting(),
447        }
448    }
449}
450
451impl<'de, T: Send, A: Deserialize<'de, T>> Deserialize<'de, T> for SkipBlank<A> {
452    fn deserialize_into<'out>(
453        out: &'out mut Option<T>,
454        state: &mut State,
455    ) -> SinkHandle<'out, 'de> {
456        // SAFETY: `A` is an adapter, the sink only holds a marker of it
457        unsafe {
458            SinkHandle::arena_unbounded(SkipBlankSink::<T, A>::Pending(out, PhantomData), state)
459        }
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}