mirror of
https://github.com/simonask/libyaml-safer
synced 2024-11-10 05:44:17 +00:00
Move yaml_parser_load to Document::load
This commit is contained in:
parent
dc69732a25
commit
eae9fe8a4c
4 changed files with 366 additions and 396 deletions
362
src/document.rs
362
src/document.rs
|
@ -1,6 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
MappingStyle, Mark, ScalarStyle, SequenceStyle, TagDirective, VersionDirective,
|
AliasData, ComposerError, Event, EventData, MappingStyle, Mark, Parser, ScalarStyle,
|
||||||
DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG,
|
SequenceStyle, TagDirective, VersionDirective, DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG,
|
||||||
|
DEFAULT_SEQUENCE_TAG,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The document structure.
|
/// The document structure.
|
||||||
|
@ -248,4 +249,361 @@ impl Document {
|
||||||
pairs.push(pair);
|
pairs.push(pair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse the input stream and produce the next YAML document.
|
||||||
|
///
|
||||||
|
/// Call this function subsequently to produce a sequence of documents
|
||||||
|
/// constituting the input stream.
|
||||||
|
///
|
||||||
|
/// If the produced document has no root node, it means that the document end
|
||||||
|
/// has been reached.
|
||||||
|
///
|
||||||
|
/// An application must not alternate the calls of
|
||||||
|
/// [`yaml_parser_load()`](crate::yaml_parser_load) with the calls of
|
||||||
|
/// [`yaml_parser_scan()`](crate::yaml_parser_scan) or
|
||||||
|
/// [`yaml_parser_parse()`](crate::yaml_parser_parse). Doing this will break the
|
||||||
|
/// parser.
|
||||||
|
pub fn load(parser: &mut Parser) -> Result<Document, ComposerError> {
|
||||||
|
let mut document = Document::new(None, &[], false, false);
|
||||||
|
document.nodes.reserve(16);
|
||||||
|
|
||||||
|
if !parser.stream_start_produced {
|
||||||
|
match parser.parse() {
|
||||||
|
Ok(Event {
|
||||||
|
data: EventData::StreamStart { .. },
|
||||||
|
..
|
||||||
|
}) => (),
|
||||||
|
Ok(_) => panic!("expected stream start"),
|
||||||
|
Err(err) => {
|
||||||
|
parser.delete_aliases();
|
||||||
|
return Err(err.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if parser.stream_end_produced {
|
||||||
|
return Ok(document);
|
||||||
|
}
|
||||||
|
let err: ComposerError;
|
||||||
|
match parser.parse() {
|
||||||
|
Ok(event) => {
|
||||||
|
if let EventData::StreamEnd = &event.data {
|
||||||
|
return Ok(document);
|
||||||
|
}
|
||||||
|
parser.aliases.reserve(16);
|
||||||
|
match document.load_document(parser, event) {
|
||||||
|
Ok(()) => {
|
||||||
|
parser.delete_aliases();
|
||||||
|
return Ok(document);
|
||||||
|
}
|
||||||
|
Err(e) => err = e,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => err = e.into(),
|
||||||
|
}
|
||||||
|
parser.delete_aliases();
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_composer_error<T>(
|
||||||
|
problem: &'static str,
|
||||||
|
problem_mark: Mark,
|
||||||
|
) -> Result<T, ComposerError> {
|
||||||
|
Err(ComposerError::Problem {
|
||||||
|
problem,
|
||||||
|
mark: problem_mark,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_composer_error_context<T>(
|
||||||
|
context: &'static str,
|
||||||
|
context_mark: Mark,
|
||||||
|
problem: &'static str,
|
||||||
|
problem_mark: Mark,
|
||||||
|
) -> Result<T, ComposerError> {
|
||||||
|
Err(ComposerError::ProblemWithContext {
|
||||||
|
context,
|
||||||
|
context_mark,
|
||||||
|
problem,
|
||||||
|
mark: problem_mark,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_document(&mut self, parser: &mut Parser, event: Event) -> Result<(), ComposerError> {
|
||||||
|
let mut ctx = vec![];
|
||||||
|
if let EventData::DocumentStart {
|
||||||
|
version_directive,
|
||||||
|
tag_directives,
|
||||||
|
implicit,
|
||||||
|
} = event.data
|
||||||
|
{
|
||||||
|
self.version_directive = version_directive;
|
||||||
|
self.tag_directives = tag_directives;
|
||||||
|
self.start_implicit = implicit;
|
||||||
|
self.start_mark = event.start_mark;
|
||||||
|
ctx.reserve(16);
|
||||||
|
if let Err(err) = self.load_nodes(parser, &mut ctx) {
|
||||||
|
ctx.clear();
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
ctx.clear();
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
panic!("Expected YAML_DOCUMENT_START_EVENT")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_nodes(&mut self, parser: &mut Parser, ctx: &mut Vec<i32>) -> Result<(), ComposerError> {
|
||||||
|
let end_implicit;
|
||||||
|
let end_mark;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let event = parser.parse()?;
|
||||||
|
match event.data {
|
||||||
|
EventData::NoEvent => panic!("empty event"),
|
||||||
|
EventData::StreamStart { .. } => panic!("unexpected stream start event"),
|
||||||
|
EventData::StreamEnd => panic!("unexpected stream end event"),
|
||||||
|
EventData::DocumentStart { .. } => panic!("unexpected document start event"),
|
||||||
|
EventData::DocumentEnd { implicit } => {
|
||||||
|
end_implicit = implicit;
|
||||||
|
end_mark = event.end_mark;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
EventData::Alias { .. } => {
|
||||||
|
self.load_alias(parser, event, ctx)?;
|
||||||
|
}
|
||||||
|
EventData::Scalar { .. } => {
|
||||||
|
self.load_scalar(parser, event, ctx)?;
|
||||||
|
}
|
||||||
|
EventData::SequenceStart { .. } => {
|
||||||
|
self.load_sequence(parser, event, ctx)?;
|
||||||
|
}
|
||||||
|
EventData::SequenceEnd => {
|
||||||
|
self.load_sequence_end(event, ctx)?;
|
||||||
|
}
|
||||||
|
EventData::MappingStart { .. } => {
|
||||||
|
self.load_mapping(parser, event, ctx)?;
|
||||||
|
}
|
||||||
|
EventData::MappingEnd => {
|
||||||
|
self.load_mapping_end(event, ctx)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.end_implicit = end_implicit;
|
||||||
|
self.end_mark = end_mark;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_anchor(
|
||||||
|
&mut self,
|
||||||
|
parser: &mut Parser,
|
||||||
|
index: i32,
|
||||||
|
anchor: Option<String>,
|
||||||
|
) -> Result<(), ComposerError> {
|
||||||
|
let Some(anchor) = anchor else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
let data = AliasData {
|
||||||
|
anchor,
|
||||||
|
index,
|
||||||
|
mark: self.nodes[index as usize - 1].start_mark,
|
||||||
|
};
|
||||||
|
for alias_data in &parser.aliases {
|
||||||
|
if alias_data.anchor == data.anchor {
|
||||||
|
return Self::set_composer_error_context(
|
||||||
|
"found duplicate anchor; first occurrence",
|
||||||
|
alias_data.mark,
|
||||||
|
"second occurrence",
|
||||||
|
data.mark,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parser.aliases.push(data);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_node_add(&mut self, ctx: &[i32], index: i32) -> Result<(), ComposerError> {
|
||||||
|
if ctx.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let parent_index: i32 = *ctx.last().unwrap();
|
||||||
|
let parent = &mut self.nodes[parent_index as usize - 1];
|
||||||
|
match parent.data {
|
||||||
|
NodeData::Sequence { ref mut items, .. } => {
|
||||||
|
items.push(index);
|
||||||
|
}
|
||||||
|
NodeData::Mapping { ref mut pairs, .. } => {
|
||||||
|
let mut pair = NodePair::default();
|
||||||
|
let mut do_push = true;
|
||||||
|
if !pairs.is_empty() {
|
||||||
|
let p: &mut NodePair = pairs.last_mut().unwrap();
|
||||||
|
if p.key != 0 && p.value == 0 {
|
||||||
|
p.value = index;
|
||||||
|
do_push = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if do_push {
|
||||||
|
pair.key = index;
|
||||||
|
pair.value = 0;
|
||||||
|
pairs.push(pair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("document parent node is not a sequence or a mapping")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_alias(
|
||||||
|
&mut self,
|
||||||
|
parser: &mut Parser,
|
||||||
|
event: Event,
|
||||||
|
ctx: &[i32],
|
||||||
|
) -> Result<(), ComposerError> {
|
||||||
|
let EventData::Alias { anchor } = &event.data else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
for alias_data in &parser.aliases {
|
||||||
|
if alias_data.anchor == *anchor {
|
||||||
|
return self.load_node_add(ctx, alias_data.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::set_composer_error("found undefined alias", event.start_mark)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_scalar(
|
||||||
|
&mut self,
|
||||||
|
parser: &mut Parser,
|
||||||
|
event: Event,
|
||||||
|
ctx: &[i32],
|
||||||
|
) -> Result<(), ComposerError> {
|
||||||
|
let EventData::Scalar {
|
||||||
|
mut tag,
|
||||||
|
value,
|
||||||
|
style,
|
||||||
|
anchor,
|
||||||
|
..
|
||||||
|
} = event.data
|
||||||
|
else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
if tag.is_none() || tag.as_deref() == Some("!") {
|
||||||
|
tag = Some(String::from(DEFAULT_SCALAR_TAG));
|
||||||
|
}
|
||||||
|
let node = Node {
|
||||||
|
data: NodeData::Scalar { value, style },
|
||||||
|
tag,
|
||||||
|
start_mark: event.start_mark,
|
||||||
|
end_mark: event.end_mark,
|
||||||
|
};
|
||||||
|
self.nodes.push(node);
|
||||||
|
let index: i32 = self.nodes.len() as i32;
|
||||||
|
self.register_anchor(parser, index, anchor)?;
|
||||||
|
self.load_node_add(ctx, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_sequence(
|
||||||
|
&mut self,
|
||||||
|
parser: &mut Parser,
|
||||||
|
event: Event,
|
||||||
|
ctx: &mut Vec<i32>,
|
||||||
|
) -> Result<(), ComposerError> {
|
||||||
|
let EventData::SequenceStart {
|
||||||
|
anchor,
|
||||||
|
mut tag,
|
||||||
|
style,
|
||||||
|
..
|
||||||
|
} = event.data
|
||||||
|
else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut items = Vec::with_capacity(16);
|
||||||
|
|
||||||
|
if tag.is_none() || tag.as_deref() == Some("!") {
|
||||||
|
tag = Some(String::from(DEFAULT_SEQUENCE_TAG));
|
||||||
|
}
|
||||||
|
|
||||||
|
let node = Node {
|
||||||
|
data: NodeData::Sequence {
|
||||||
|
items: core::mem::take(&mut items),
|
||||||
|
style,
|
||||||
|
},
|
||||||
|
tag,
|
||||||
|
start_mark: event.start_mark,
|
||||||
|
end_mark: event.end_mark,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.nodes.push(node);
|
||||||
|
let index: i32 = self.nodes.len() as i32;
|
||||||
|
self.register_anchor(parser, index, anchor)?;
|
||||||
|
self.load_node_add(ctx, index)?;
|
||||||
|
ctx.push(index);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_sequence_end(&mut self, event: Event, ctx: &mut Vec<i32>) -> Result<(), ComposerError> {
|
||||||
|
assert!(!ctx.is_empty());
|
||||||
|
let index: i32 = *ctx.last().unwrap();
|
||||||
|
assert!(matches!(
|
||||||
|
self.nodes[index as usize - 1].data,
|
||||||
|
NodeData::Sequence { .. }
|
||||||
|
));
|
||||||
|
self.nodes[index as usize - 1].end_mark = event.end_mark;
|
||||||
|
_ = ctx.pop();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_mapping(
|
||||||
|
&mut self,
|
||||||
|
parser: &mut Parser,
|
||||||
|
event: Event,
|
||||||
|
ctx: &mut Vec<i32>,
|
||||||
|
) -> Result<(), ComposerError> {
|
||||||
|
let EventData::MappingStart {
|
||||||
|
anchor,
|
||||||
|
mut tag,
|
||||||
|
style,
|
||||||
|
..
|
||||||
|
} = event.data
|
||||||
|
else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut pairs = Vec::with_capacity(16);
|
||||||
|
|
||||||
|
if tag.is_none() || tag.as_deref() == Some("!") {
|
||||||
|
tag = Some(String::from(DEFAULT_MAPPING_TAG));
|
||||||
|
}
|
||||||
|
let node = Node {
|
||||||
|
data: NodeData::Mapping {
|
||||||
|
pairs: core::mem::take(&mut pairs),
|
||||||
|
style,
|
||||||
|
},
|
||||||
|
tag,
|
||||||
|
start_mark: event.start_mark,
|
||||||
|
end_mark: event.end_mark,
|
||||||
|
};
|
||||||
|
self.nodes.push(node);
|
||||||
|
let index: i32 = self.nodes.len() as i32;
|
||||||
|
self.register_anchor(parser, index, anchor)?;
|
||||||
|
self.load_node_add(ctx, index)?;
|
||||||
|
ctx.push(index);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_mapping_end(&mut self, event: Event, ctx: &mut Vec<i32>) -> Result<(), ComposerError> {
|
||||||
|
assert!(!ctx.is_empty());
|
||||||
|
let index: i32 = *ctx.last().unwrap();
|
||||||
|
assert!(matches!(
|
||||||
|
self.nodes[index as usize - 1].data,
|
||||||
|
NodeData::Mapping { .. }
|
||||||
|
));
|
||||||
|
self.nodes[index as usize - 1].end_mark = event.end_mark;
|
||||||
|
_ = ctx.pop();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ mod dumper;
|
||||||
mod emitter;
|
mod emitter;
|
||||||
mod error;
|
mod error;
|
||||||
mod event;
|
mod event;
|
||||||
mod loader;
|
|
||||||
mod parser;
|
mod parser;
|
||||||
mod reader;
|
mod reader;
|
||||||
mod scanner;
|
mod scanner;
|
||||||
|
@ -44,7 +43,6 @@ pub use crate::dumper::{yaml_emitter_close, yaml_emitter_dump, yaml_emitter_open
|
||||||
pub use crate::emitter::*;
|
pub use crate::emitter::*;
|
||||||
pub use crate::error::*;
|
pub use crate::error::*;
|
||||||
pub use crate::event::*;
|
pub use crate::event::*;
|
||||||
pub use crate::loader::yaml_parser_load;
|
|
||||||
pub use crate::parser::*;
|
pub use crate::parser::*;
|
||||||
pub use crate::scanner::yaml_parser_scan;
|
pub use crate::scanner::yaml_parser_scan;
|
||||||
pub use crate::token::*;
|
pub use crate::token::*;
|
||||||
|
@ -194,7 +192,7 @@ tie-fighter: '|\-*-/|'
|
||||||
// "Mark McGwire:\n hr: 65\n avg: 0.278\nSammy Sosa:\n hr: 63\n avg: 0.288\n";
|
// "Mark McGwire:\n hr: 65\n avg: 0.278\nSammy Sosa:\n hr: 63\n avg: 0.288\n";
|
||||||
let mut read_in = SANITY_INPUT.as_bytes();
|
let mut read_in = SANITY_INPUT.as_bytes();
|
||||||
parser.set_input_string(&mut read_in);
|
parser.set_input_string(&mut read_in);
|
||||||
let _doc = yaml_parser_load(&mut parser).unwrap();
|
let _doc = Document::load(&mut parser).unwrap();
|
||||||
// let mut doc = doc.assume_init();
|
// let mut doc = doc.assume_init();
|
||||||
|
|
||||||
// let mut emitter = core::mem::MaybeUninit::uninit();
|
// let mut emitter = core::mem::MaybeUninit::uninit();
|
||||||
|
@ -228,7 +226,7 @@ foo: bar
|
||||||
let mut parser = Parser::new();
|
let mut parser = Parser::new();
|
||||||
let mut input = TEST_CASE_QF4Y.as_bytes();
|
let mut input = TEST_CASE_QF4Y.as_bytes();
|
||||||
parser.set_input_string(&mut input);
|
parser.set_input_string(&mut input);
|
||||||
let _doc = yaml_parser_load(&mut parser).unwrap();
|
let _doc = Document::load(&mut parser).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
|
|
390
src/loader.rs
390
src/loader.rs
|
@ -1,390 +0,0 @@
|
||||||
use alloc::string::String;
|
|
||||||
use alloc::{vec, vec::Vec};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
AliasData, ComposerError, Document, Event, EventData, Mark, Node, NodeData, NodePair, Parser,
|
|
||||||
DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Parse the input stream and produce the next YAML document.
|
|
||||||
///
|
|
||||||
/// Call this function subsequently to produce a sequence of documents
|
|
||||||
/// constituting the input stream.
|
|
||||||
///
|
|
||||||
/// If the produced document has no root node, it means that the document end
|
|
||||||
/// has been reached.
|
|
||||||
///
|
|
||||||
/// An application must not alternate the calls of
|
|
||||||
/// [`yaml_parser_load()`](crate::yaml_parser_load) with the calls of
|
|
||||||
/// [`yaml_parser_scan()`](crate::yaml_parser_scan) or
|
|
||||||
/// [`yaml_parser_parse()`](crate::yaml_parser_parse). Doing this will break the
|
|
||||||
/// parser.
|
|
||||||
pub fn yaml_parser_load(parser: &mut Parser) -> Result<Document, ComposerError> {
|
|
||||||
let mut document = Document::new(None, &[], false, false);
|
|
||||||
document.nodes.reserve(16);
|
|
||||||
|
|
||||||
if !parser.stream_start_produced {
|
|
||||||
match parser.parse() {
|
|
||||||
Ok(Event {
|
|
||||||
data: EventData::StreamStart { .. },
|
|
||||||
..
|
|
||||||
}) => (),
|
|
||||||
Ok(_) => panic!("expected stream start"),
|
|
||||||
Err(err) => {
|
|
||||||
yaml_parser_delete_aliases(parser);
|
|
||||||
return Err(err.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if parser.stream_end_produced {
|
|
||||||
return Ok(document);
|
|
||||||
}
|
|
||||||
let err: ComposerError;
|
|
||||||
match parser.parse() {
|
|
||||||
Ok(event) => {
|
|
||||||
if let EventData::StreamEnd = &event.data {
|
|
||||||
return Ok(document);
|
|
||||||
}
|
|
||||||
parser.aliases.reserve(16);
|
|
||||||
match yaml_parser_load_document(parser, event, &mut document) {
|
|
||||||
Ok(()) => {
|
|
||||||
yaml_parser_delete_aliases(parser);
|
|
||||||
return Ok(document);
|
|
||||||
}
|
|
||||||
Err(e) => err = e,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => err = e.into(),
|
|
||||||
}
|
|
||||||
yaml_parser_delete_aliases(parser);
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_set_composer_error<T>(
|
|
||||||
problem: &'static str,
|
|
||||||
problem_mark: Mark,
|
|
||||||
) -> Result<T, ComposerError> {
|
|
||||||
Err(ComposerError::Problem {
|
|
||||||
problem,
|
|
||||||
mark: problem_mark,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_set_composer_error_context<T>(
|
|
||||||
context: &'static str,
|
|
||||||
context_mark: Mark,
|
|
||||||
problem: &'static str,
|
|
||||||
problem_mark: Mark,
|
|
||||||
) -> Result<T, ComposerError> {
|
|
||||||
Err(ComposerError::ProblemWithContext {
|
|
||||||
context,
|
|
||||||
context_mark,
|
|
||||||
problem,
|
|
||||||
mark: problem_mark,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_delete_aliases(parser: &mut Parser) {
|
|
||||||
parser.aliases.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_load_document(
|
|
||||||
parser: &mut Parser,
|
|
||||||
event: Event,
|
|
||||||
document: &mut Document,
|
|
||||||
) -> Result<(), ComposerError> {
|
|
||||||
let mut ctx = vec![];
|
|
||||||
if let EventData::DocumentStart {
|
|
||||||
version_directive,
|
|
||||||
tag_directives,
|
|
||||||
implicit,
|
|
||||||
} = event.data
|
|
||||||
{
|
|
||||||
document.version_directive = version_directive;
|
|
||||||
document.tag_directives = tag_directives;
|
|
||||||
document.start_implicit = implicit;
|
|
||||||
document.start_mark = event.start_mark;
|
|
||||||
ctx.reserve(16);
|
|
||||||
if let Err(err) = yaml_parser_load_nodes(parser, document, &mut ctx) {
|
|
||||||
ctx.clear();
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
ctx.clear();
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
panic!("Expected YAML_DOCUMENT_START_EVENT")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_load_nodes(
|
|
||||||
parser: &mut Parser,
|
|
||||||
document: &mut Document,
|
|
||||||
ctx: &mut Vec<i32>,
|
|
||||||
) -> Result<(), ComposerError> {
|
|
||||||
let end_implicit;
|
|
||||||
let end_mark;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let event = parser.parse()?;
|
|
||||||
match event.data {
|
|
||||||
EventData::NoEvent => panic!("empty event"),
|
|
||||||
EventData::StreamStart { .. } => panic!("unexpected stream start event"),
|
|
||||||
EventData::StreamEnd => panic!("unexpected stream end event"),
|
|
||||||
EventData::DocumentStart { .. } => panic!("unexpected document start event"),
|
|
||||||
EventData::DocumentEnd { implicit } => {
|
|
||||||
end_implicit = implicit;
|
|
||||||
end_mark = event.end_mark;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
EventData::Alias { .. } => {
|
|
||||||
yaml_parser_load_alias(parser, event, document, ctx)?;
|
|
||||||
}
|
|
||||||
EventData::Scalar { .. } => {
|
|
||||||
yaml_parser_load_scalar(parser, event, document, ctx)?;
|
|
||||||
}
|
|
||||||
EventData::SequenceStart { .. } => {
|
|
||||||
yaml_parser_load_sequence(parser, event, document, ctx)?;
|
|
||||||
}
|
|
||||||
EventData::SequenceEnd => {
|
|
||||||
yaml_parser_load_sequence_end(parser, event, document, ctx)?;
|
|
||||||
}
|
|
||||||
EventData::MappingStart { .. } => {
|
|
||||||
yaml_parser_load_mapping(parser, event, document, ctx)?;
|
|
||||||
}
|
|
||||||
EventData::MappingEnd => {
|
|
||||||
yaml_parser_load_mapping_end(parser, event, document, ctx)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.end_implicit = end_implicit;
|
|
||||||
document.end_mark = end_mark;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_register_anchor(
|
|
||||||
parser: &mut Parser,
|
|
||||||
document: &mut Document,
|
|
||||||
index: i32,
|
|
||||||
anchor: Option<String>,
|
|
||||||
) -> Result<(), ComposerError> {
|
|
||||||
let Some(anchor) = anchor else {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
let data = AliasData {
|
|
||||||
anchor,
|
|
||||||
index,
|
|
||||||
mark: document.nodes[index as usize - 1].start_mark,
|
|
||||||
};
|
|
||||||
for alias_data in &parser.aliases {
|
|
||||||
if alias_data.anchor == data.anchor {
|
|
||||||
return yaml_parser_set_composer_error_context(
|
|
||||||
"found duplicate anchor; first occurrence",
|
|
||||||
alias_data.mark,
|
|
||||||
"second occurrence",
|
|
||||||
data.mark,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parser.aliases.push(data);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_load_node_add(
|
|
||||||
document: &mut Document,
|
|
||||||
ctx: &[i32],
|
|
||||||
index: i32,
|
|
||||||
) -> Result<(), ComposerError> {
|
|
||||||
if ctx.is_empty() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
let parent_index: i32 = *ctx.last().unwrap();
|
|
||||||
let parent = &mut document.nodes[parent_index as usize - 1];
|
|
||||||
match parent.data {
|
|
||||||
NodeData::Sequence { ref mut items, .. } => {
|
|
||||||
items.push(index);
|
|
||||||
}
|
|
||||||
NodeData::Mapping { ref mut pairs, .. } => {
|
|
||||||
let mut pair = NodePair::default();
|
|
||||||
let mut do_push = true;
|
|
||||||
if !pairs.is_empty() {
|
|
||||||
let p: &mut NodePair = pairs.last_mut().unwrap();
|
|
||||||
if p.key != 0 && p.value == 0 {
|
|
||||||
p.value = index;
|
|
||||||
do_push = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if do_push {
|
|
||||||
pair.key = index;
|
|
||||||
pair.value = 0;
|
|
||||||
pairs.push(pair);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
panic!("document parent node is not a sequence or a mapping")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_load_alias(
|
|
||||||
parser: &mut Parser,
|
|
||||||
event: Event,
|
|
||||||
document: &mut Document,
|
|
||||||
ctx: &[i32],
|
|
||||||
) -> Result<(), ComposerError> {
|
|
||||||
let EventData::Alias { anchor } = &event.data else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
for alias_data in &parser.aliases {
|
|
||||||
if alias_data.anchor == *anchor {
|
|
||||||
return yaml_parser_load_node_add(document, ctx, alias_data.index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
yaml_parser_set_composer_error("found undefined alias", event.start_mark)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_load_scalar(
|
|
||||||
parser: &mut Parser,
|
|
||||||
event: Event,
|
|
||||||
document: &mut Document,
|
|
||||||
ctx: &[i32],
|
|
||||||
) -> Result<(), ComposerError> {
|
|
||||||
let EventData::Scalar {
|
|
||||||
mut tag,
|
|
||||||
value,
|
|
||||||
style,
|
|
||||||
anchor,
|
|
||||||
..
|
|
||||||
} = event.data
|
|
||||||
else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
if tag.is_none() || tag.as_deref() == Some("!") {
|
|
||||||
tag = Some(String::from(DEFAULT_SCALAR_TAG));
|
|
||||||
}
|
|
||||||
let node = Node {
|
|
||||||
data: NodeData::Scalar { value, style },
|
|
||||||
tag,
|
|
||||||
start_mark: event.start_mark,
|
|
||||||
end_mark: event.end_mark,
|
|
||||||
};
|
|
||||||
document.nodes.push(node);
|
|
||||||
let index: i32 = document.nodes.len() as i32;
|
|
||||||
yaml_parser_register_anchor(parser, document, index, anchor)?;
|
|
||||||
yaml_parser_load_node_add(document, ctx, index)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_load_sequence(
|
|
||||||
parser: &mut Parser,
|
|
||||||
event: Event,
|
|
||||||
document: &mut Document,
|
|
||||||
ctx: &mut Vec<i32>,
|
|
||||||
) -> Result<(), ComposerError> {
|
|
||||||
let EventData::SequenceStart {
|
|
||||||
anchor,
|
|
||||||
mut tag,
|
|
||||||
style,
|
|
||||||
..
|
|
||||||
} = event.data
|
|
||||||
else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut items = Vec::with_capacity(16);
|
|
||||||
|
|
||||||
if tag.is_none() || tag.as_deref() == Some("!") {
|
|
||||||
tag = Some(String::from(DEFAULT_SEQUENCE_TAG));
|
|
||||||
}
|
|
||||||
|
|
||||||
let node = Node {
|
|
||||||
data: NodeData::Sequence {
|
|
||||||
items: core::mem::take(&mut items),
|
|
||||||
style,
|
|
||||||
},
|
|
||||||
tag,
|
|
||||||
start_mark: event.start_mark,
|
|
||||||
end_mark: event.end_mark,
|
|
||||||
};
|
|
||||||
|
|
||||||
document.nodes.push(node);
|
|
||||||
let index: i32 = document.nodes.len() as i32;
|
|
||||||
yaml_parser_register_anchor(parser, document, index, anchor)?;
|
|
||||||
yaml_parser_load_node_add(document, ctx, index)?;
|
|
||||||
ctx.push(index);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_load_sequence_end(
|
|
||||||
_parser: &mut Parser,
|
|
||||||
event: Event,
|
|
||||||
document: &mut Document,
|
|
||||||
ctx: &mut Vec<i32>,
|
|
||||||
) -> Result<(), ComposerError> {
|
|
||||||
assert!(!ctx.is_empty());
|
|
||||||
let index: i32 = *ctx.last().unwrap();
|
|
||||||
assert!(matches!(
|
|
||||||
document.nodes[index as usize - 1].data,
|
|
||||||
NodeData::Sequence { .. }
|
|
||||||
));
|
|
||||||
document.nodes[index as usize - 1].end_mark = event.end_mark;
|
|
||||||
_ = ctx.pop();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_load_mapping(
|
|
||||||
parser: &mut Parser,
|
|
||||||
event: Event,
|
|
||||||
document: &mut Document,
|
|
||||||
ctx: &mut Vec<i32>,
|
|
||||||
) -> Result<(), ComposerError> {
|
|
||||||
let EventData::MappingStart {
|
|
||||||
anchor,
|
|
||||||
mut tag,
|
|
||||||
style,
|
|
||||||
..
|
|
||||||
} = event.data
|
|
||||||
else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut pairs = Vec::with_capacity(16);
|
|
||||||
|
|
||||||
if tag.is_none() || tag.as_deref() == Some("!") {
|
|
||||||
tag = Some(String::from(DEFAULT_MAPPING_TAG));
|
|
||||||
}
|
|
||||||
let node = Node {
|
|
||||||
data: NodeData::Mapping {
|
|
||||||
pairs: core::mem::take(&mut pairs),
|
|
||||||
style,
|
|
||||||
},
|
|
||||||
tag,
|
|
||||||
start_mark: event.start_mark,
|
|
||||||
end_mark: event.end_mark,
|
|
||||||
};
|
|
||||||
document.nodes.push(node);
|
|
||||||
let index: i32 = document.nodes.len() as i32;
|
|
||||||
yaml_parser_register_anchor(parser, document, index, anchor)?;
|
|
||||||
yaml_parser_load_node_add(document, ctx, index)?;
|
|
||||||
ctx.push(index);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn yaml_parser_load_mapping_end(
|
|
||||||
_parser: &mut Parser,
|
|
||||||
event: Event,
|
|
||||||
document: &mut Document,
|
|
||||||
ctx: &mut Vec<i32>,
|
|
||||||
) -> Result<(), ComposerError> {
|
|
||||||
assert!(!ctx.is_empty());
|
|
||||||
let index: i32 = *ctx.last().unwrap();
|
|
||||||
assert!(matches!(
|
|
||||||
document.nodes[index as usize - 1].data,
|
|
||||||
NodeData::Mapping { .. }
|
|
||||||
));
|
|
||||||
document.nodes[index as usize - 1].end_mark = event.end_mark;
|
|
||||||
_ = ctx.pop();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -1081,4 +1081,8 @@ impl<'r> Parser<'r> {
|
||||||
self.tag_directives.push(value);
|
self.tag_directives.push(value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn delete_aliases(&mut self) {
|
||||||
|
self.aliases.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue