1 use crate::de::{Event, Progress};
2 use crate::error::{self, Error, ErrorImpl, Result};
3 use crate::libyaml::error::Mark;
4 use crate::libyaml::parser::{Event as YamlEvent, Parser};
5 use std::borrow::Cow;
6 use std::collections::BTreeMap;
7 use std::sync::Arc;
8 
9 pub(crate) struct Loader<'input> {
10     parser: Option<Parser<'input>>,
11     document_count: usize,
12 }
13 
14 pub(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 
21 impl<'input> Loader<'input> {
new(progress: Progress<'input>) -> Result<Self>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 
next_document(&mut self) -> Option<Document<'input>>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 }
120