serde_yaml/
loader.rs

1use crate::de::{Event, Progress};
2use crate::error::{self, Error, ErrorImpl, Result};
3use crate::libyaml::error::Mark;
4use crate::libyaml::parser::{Event as YamlEvent, Parser};
5use std::borrow::Cow;
6use std::collections::BTreeMap;
7use std::sync::Arc;
8
9pub(crate) struct Loader<'input> {
10    parser: Option<Parser<'input>>,
11    document_count: usize,
12}
13
14pub(crate) struct Document<'input> {
15    pub events: Vec<(Event<'input>, Mark)>,
16    pub error: Option<Arc<ErrorImpl>>,
17    /// Map from alias id to index in events.
18    pub aliases: BTreeMap<usize, usize>,
19}
20
21impl<'input> Loader<'input> {
22    pub fn new(progress: Progress<'input>) -> Result<Self> {
23        let input = match progress {
24            Progress::Str(s) => Cow::Borrowed(s.as_bytes()),
25            Progress::Slice(bytes) => Cow::Borrowed(bytes),
26            Progress::Read(mut rdr) => {
27                let mut buffer = Vec::new();
28                if let Err(io_error) = rdr.read_to_end(&mut buffer) {
29                    return Err(error::new(ErrorImpl::Io(io_error)));
30                }
31                Cow::Owned(buffer)
32            }
33            Progress::Iterable(_) | Progress::Document(_) => unreachable!(),
34            Progress::Fail(err) => return Err(error::shared(err)),
35        };
36
37        Ok(Loader {
38            parser: Some(Parser::new(input)),
39            document_count: 0,
40        })
41    }
42
43    pub fn next_document(&mut self) -> Option<Document<'input>> {
44        let parser = match &mut self.parser {
45            Some(parser) => parser,
46            None => return None,
47        };
48
49        let first = self.document_count == 0;
50        self.document_count += 1;
51
52        let mut anchors = BTreeMap::new();
53        let mut document = Document {
54            events: Vec::new(),
55            error: None,
56            aliases: BTreeMap::new(),
57        };
58
59        loop {
60            let (event, mark) = match parser.next() {
61                Ok((event, mark)) => (event, mark),
62                Err(err) => {
63                    document.error = Some(Error::from(err).shared());
64                    return Some(document);
65                }
66            };
67            let event = match event {
68                YamlEvent::StreamStart => continue,
69                YamlEvent::StreamEnd => {
70                    self.parser = None;
71                    return if first {
72                        if document.events.is_empty() {
73                            document.events.push((Event::Void, mark));
74                        }
75                        Some(document)
76                    } else {
77                        None
78                    };
79                }
80                YamlEvent::DocumentStart => continue,
81                YamlEvent::DocumentEnd => return Some(document),
82                YamlEvent::Alias(alias) => match anchors.get(&alias) {
83                    Some(id) => Event::Alias(*id),
84                    None => {
85                        document.error = Some(error::new(ErrorImpl::UnknownAnchor(mark)).shared());
86                        return Some(document);
87                    }
88                },
89                YamlEvent::Scalar(mut scalar) => {
90                    if let Some(anchor) = scalar.anchor.take() {
91                        let id = anchors.len();
92                        anchors.insert(anchor, id);
93                        document.aliases.insert(id, document.events.len());
94                    }
95                    Event::Scalar(scalar)
96                }
97                YamlEvent::SequenceStart(mut sequence_start) => {
98                    if let Some(anchor) = sequence_start.anchor.take() {
99                        let id = anchors.len();
100                        anchors.insert(anchor, id);
101                        document.aliases.insert(id, document.events.len());
102                    }
103                    Event::SequenceStart(sequence_start)
104                }
105                YamlEvent::SequenceEnd => Event::SequenceEnd,
106                YamlEvent::MappingStart(mut mapping_start) => {
107                    if let Some(anchor) = mapping_start.anchor.take() {
108                        let id = anchors.len();
109                        anchors.insert(anchor, id);
110                        document.aliases.insert(id, document.events.len());
111                    }
112                    Event::MappingStart(mapping_start)
113                }
114                YamlEvent::MappingEnd => Event::MappingEnd,
115            };
116            document.events.push((event, mark));
117        }
118    }
119}