1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use std::borrow::Cow;
use std::cell::RefCell;
use std::rc::Rc;

use deser::de::{DeserializerState, Sink, SinkHandle};
use deser::{Atom, Descriptor, Error};

use crate::{Path, PathSegment};

enum Container {
    None,
    Map(Rc<RefCell<Option<PathSegment>>>),
    Seq(usize),
}

/// A path sink tracks the current path during deserialization.
pub struct PathSink<'a> {
    sink: SinkHandle<'a>,
    container: Container,
    set_segment: Option<PathSegment>,
}

impl<'a> PathSink<'a> {
    /// Wraps a sink.
    pub fn wrap(sink: &'a mut dyn Sink) -> PathSink<'a> {
        PathSink::wrap_ref(SinkHandle::to(sink))
    }

    /// Wraps a sink ref.
    pub fn wrap_ref(sink: SinkHandle<'a>) -> PathSink<'a> {
        PathSink {
            sink,
            container: Container::None,
            set_segment: None,
        }
    }

    fn set_segment(&mut self, state: &DeserializerState) {
        if let Some(segment) = self.set_segment.take() {
            *state.get_mut::<Path>().segments.last_mut().unwrap() = segment;
        }
    }
}

impl<'a> Sink for PathSink<'a> {
    fn atom(&mut self, atom: Atom, state: &DeserializerState) -> Result<(), Error> {
        self.set_segment(state);
        if let Container::Map(ref capture) = self.container {
            *capture.borrow_mut() = match atom {
                Atom::Str(ref value) => Some(PathSegment::Key(value.to_string())),
                Atom::U64(value) => Some(PathSegment::Index(value as usize)),
                Atom::I64(value) => Some(PathSegment::Index(value as usize)),
                _ => None,
            };
        }
        self.sink.atom(atom, state)
    }

    fn map(&mut self, state: &DeserializerState) -> Result<(), Error> {
        self.set_segment(state);
        state.get_mut::<Path>().segments.push(PathSegment::Unknown);
        self.container = Container::Map(Rc::default());
        self.sink.map(state)
    }

    fn seq(&mut self, state: &DeserializerState) -> Result<(), Error> {
        self.set_segment(state);
        state.get_mut::<Path>().segments.push(PathSegment::Unknown);
        self.container = Container::Seq(0);
        self.sink.seq(state)
    }

    fn next_key(&mut self, state: &DeserializerState) -> Result<SinkHandle, Error> {
        self.sink.next_key(state).map(|sink| {
            SinkHandle::boxed(PathSink {
                sink,
                container: match self.container {
                    Container::Map(ref capture) => Container::Map(capture.clone()),
                    _ => unreachable!(),
                },
                set_segment: None,
            })
        })
    }

    fn next_value(&mut self, state: &DeserializerState) -> Result<SinkHandle, Error> {
        let set_segment = match self.container {
            Container::None => None,
            Container::Map(ref captured_key) => captured_key.borrow_mut().take(),
            Container::Seq(ref mut index) => {
                let old_index = *index;
                *index += 1;
                Some(PathSegment::Index(old_index))
            }
        };
        self.sink.next_value(state).map(|sink| {
            SinkHandle::boxed(PathSink {
                sink,
                container: Container::None,
                set_segment,
            })
        })
    }

    fn finish(&mut self, state: &DeserializerState) -> Result<(), Error> {
        self.sink.finish(state)
    }

    fn descriptor(&self) -> &dyn Descriptor {
        self.sink.descriptor()
    }

    fn expecting(&self) -> Cow<'_, str> {
        self.sink.expecting()
    }
}