1use std::borrow::Cow;
2use std::cell::RefCell;
3use std::rc::Rc;
4
5use deser::de::{DeserializerState, Sink, SinkHandle};
6use deser::{Atom, Descriptor, Error};
7
8use crate::{Path, PathSegment};
9
10enum Container {
11 None,
12 Map(Rc<RefCell<Option<PathSegment>>>),
13 Seq(usize),
14}
15
16pub struct PathSink<'a> {
18 sink: SinkHandle<'a>,
19 container: Container,
20 set_segment: Option<PathSegment>,
21}
22
23impl<'a> PathSink<'a> {
24 pub fn wrap(sink: &'a mut dyn Sink) -> PathSink<'a> {
26 PathSink::wrap_ref(SinkHandle::to(sink))
27 }
28
29 pub fn wrap_ref(sink: SinkHandle<'a>) -> PathSink<'a> {
31 PathSink {
32 sink,
33 container: Container::None,
34 set_segment: None,
35 }
36 }
37
38 fn set_segment(&mut self, state: &DeserializerState) {
39 if let Some(segment) = self.set_segment.take() {
40 *state.get_mut::<Path>().segments.last_mut().unwrap() = segment;
41 }
42 }
43}
44
45impl<'a> Sink for PathSink<'a> {
46 fn atom(&mut self, atom: Atom, state: &DeserializerState) -> Result<(), Error> {
47 self.set_segment(state);
48 if let Container::Map(ref capture) = self.container {
49 *capture.borrow_mut() = match atom {
50 Atom::Str(ref value) => Some(PathSegment::Key(value.to_string())),
51 Atom::U64(value) => Some(PathSegment::Index(value as usize)),
52 Atom::I64(value) => Some(PathSegment::Index(value as usize)),
53 _ => None,
54 };
55 }
56 self.sink.atom(atom, state)
57 }
58
59 fn map(&mut self, state: &DeserializerState) -> Result<(), Error> {
60 self.set_segment(state);
61 state.get_mut::<Path>().segments.push(PathSegment::Unknown);
62 self.container = Container::Map(Rc::default());
63 self.sink.map(state)
64 }
65
66 fn seq(&mut self, state: &DeserializerState) -> Result<(), Error> {
67 self.set_segment(state);
68 state.get_mut::<Path>().segments.push(PathSegment::Unknown);
69 self.container = Container::Seq(0);
70 self.sink.seq(state)
71 }
72
73 fn next_key(&mut self, state: &DeserializerState) -> Result<SinkHandle, Error> {
74 self.sink.next_key(state).map(|sink| {
75 SinkHandle::boxed(PathSink {
76 sink,
77 container: match self.container {
78 Container::Map(ref capture) => Container::Map(capture.clone()),
79 _ => unreachable!(),
80 },
81 set_segment: None,
82 })
83 })
84 }
85
86 fn next_value(&mut self, state: &DeserializerState) -> Result<SinkHandle, Error> {
87 let set_segment = match self.container {
88 Container::None => None,
89 Container::Map(ref captured_key) => captured_key.borrow_mut().take(),
90 Container::Seq(ref mut index) => {
91 let old_index = *index;
92 *index += 1;
93 Some(PathSegment::Index(old_index))
94 }
95 };
96 self.sink.next_value(state).map(|sink| {
97 SinkHandle::boxed(PathSink {
98 sink,
99 container: Container::None,
100 set_segment,
101 })
102 })
103 }
104
105 fn finish(&mut self, state: &DeserializerState) -> Result<(), Error> {
106 self.sink.finish(state)
107 }
108
109 fn descriptor(&self) -> &dyn Descriptor {
110 self.sink.descriptor()
111 }
112
113 fn expecting(&self) -> Cow<'_, str> {
114 self.sink.expecting()
115 }
116}