1use 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
25pub struct Separated<const SEP: char = ',', A = Same>(PhantomData<fn() -> A>);
63
64pub struct TrimWhitespace<A = Same>(PhantomData<fn() -> A>);
95
96pub struct SkipBlank<A = Same>(PhantomData<fn() -> A>);
129
130#[derive(Clone, Copy)]
132enum TextOp {
133 Split(char),
135 Trim,
137}
138
139struct 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
153fn 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
160fn 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
168fn 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
186fn 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#[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
222fn 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#[inline]
332fn is_blank(atom: &Atom) -> bool {
333 matches!(atom, Atom::Str(text) | Atom::Lexical(text) if text.trim().is_empty())
334}
335
336enum 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 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 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 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
641fn 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 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
670fn 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
684fn 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
720macro_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}