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