mirror of
https://github.com/simonask/libyaml-safer
synced 2024-11-22 19:33:03 +00:00
Parser: Safe token queue, Rustify errors
This commit is contained in:
parent
77716c3b53
commit
04168ca612
9 changed files with 583 additions and 699 deletions
|
@ -14,9 +14,9 @@ description = "Safer libyaml port, based on unsafe-libyaml"
|
||||||
documentation = "https://docs.rs/libyaml-safer"
|
documentation = "https://docs.rs/libyaml-safer"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
keywords = ["yaml"]
|
keywords = ["yaml"]
|
||||||
license = "MIT"
|
license = "Apache 2.0 OR MIT"
|
||||||
repository = "https://github.com/simonask/libyaml-safer"
|
repository = "https://github.com/simonask/libyaml-safer"
|
||||||
rust-version = "1.56"
|
rust-version = "1.70"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -26,6 +26,9 @@ unsafe-libyaml-test-suite = { path = "tests/data" }
|
||||||
[lib]
|
[lib]
|
||||||
doc-scrape-examples = false
|
doc-scrape-examples = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
thiserror = "1.0"
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-unknown-linux-gnu"]
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
rustdoc-args = ["--generate-link-to-definition"]
|
rustdoc-args = ["--generate-link-to-definition"]
|
||||||
|
|
|
@ -12,14 +12,12 @@
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use libyaml_safer::{
|
use libyaml_safer::{
|
||||||
yaml_event_delete, yaml_event_t, yaml_parser_delete, yaml_parser_initialize, yaml_parser_parse,
|
yaml_parser_delete, yaml_parser_initialize, yaml_parser_parse, yaml_parser_set_input,
|
||||||
yaml_parser_set_input, yaml_parser_t, YamlEventData, YAML_DOUBLE_QUOTED_SCALAR_STYLE,
|
yaml_parser_t, YamlEventData, YAML_DOUBLE_QUOTED_SCALAR_STYLE, YAML_FOLDED_SCALAR_STYLE,
|
||||||
YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE, YAML_PLAIN_SCALAR_STYLE,
|
YAML_LITERAL_SCALAR_STYLE, YAML_PLAIN_SCALAR_STYLE, YAML_SINGLE_QUOTED_SCALAR_STYLE,
|
||||||
YAML_SINGLE_QUOTED_SCALAR_STYLE,
|
|
||||||
};
|
};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::Write as _;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
|
@ -38,21 +36,15 @@ pub(crate) unsafe fn unsafe_main(
|
||||||
|
|
||||||
yaml_parser_set_input(&mut parser, stdin);
|
yaml_parser_set_input(&mut parser, stdin);
|
||||||
|
|
||||||
let mut event = yaml_event_t::default();
|
|
||||||
loop {
|
loop {
|
||||||
if yaml_parser_parse(&mut parser, &mut event).is_err() {
|
let event = match yaml_parser_parse(&mut parser) {
|
||||||
let mut error = format!("Parse error: {}", parser.problem.unwrap_or(""));
|
Err(err) => {
|
||||||
if parser.problem_mark.line != 0 || parser.problem_mark.column != 0 {
|
let error = format!("Parse error: {}", err);
|
||||||
let _ = write!(
|
yaml_parser_delete(&mut parser);
|
||||||
error,
|
return Err(error.into());
|
||||||
"\nLine: {} Column: {}",
|
|
||||||
(parser.problem_mark.line).wrapping_add(1_u64),
|
|
||||||
(parser.problem_mark.column).wrapping_add(1_u64),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
yaml_parser_delete(&mut parser);
|
Ok(event) => event,
|
||||||
return Err(error.into());
|
};
|
||||||
}
|
|
||||||
|
|
||||||
let mut is_end = false;
|
let mut is_end = false;
|
||||||
|
|
||||||
|
@ -137,7 +129,6 @@ pub(crate) unsafe fn unsafe_main(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
yaml_event_delete(&mut event);
|
|
||||||
if is_end {
|
if is_end {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
40
src/error.rs
40
src/error.rs
|
@ -30,7 +30,7 @@ pub enum ReaderError {
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum ScannerError {
|
pub enum ScannerError {
|
||||||
#[error("{problem}")]
|
#[error("{}:{}: {} {} ({}:{})", problem_mark.line, problem_mark.column, problem, context, context_mark.line, context_mark.column)]
|
||||||
Problem {
|
Problem {
|
||||||
context: &'static str,
|
context: &'static str,
|
||||||
context_mark: yaml_mark_t,
|
context_mark: yaml_mark_t,
|
||||||
|
@ -40,3 +40,41 @@ pub enum ScannerError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Reader(#[from] ReaderError),
|
Reader(#[from] ReaderError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum ParserError {
|
||||||
|
#[error("no more tokens")]
|
||||||
|
UnexpectedEof,
|
||||||
|
#[error("{}:{}: {}", mark.line, mark.column, problem)]
|
||||||
|
Problem {
|
||||||
|
problem: &'static str,
|
||||||
|
mark: yaml_mark_t,
|
||||||
|
},
|
||||||
|
#[error("{}:{}: {} {} ({}:{})", mark.line, mark.column, problem, context, context_mark.line, context_mark.column)]
|
||||||
|
ProblemWithContext {
|
||||||
|
context: &'static str,
|
||||||
|
context_mark: yaml_mark_t,
|
||||||
|
problem: &'static str,
|
||||||
|
mark: yaml_mark_t,
|
||||||
|
},
|
||||||
|
#[error(transparent)]
|
||||||
|
Scanner(#[from] ScannerError),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum ComposerError {
|
||||||
|
#[error("{}:{}: {}", mark.line, mark.column, problem)]
|
||||||
|
Problem {
|
||||||
|
problem: &'static str,
|
||||||
|
mark: yaml_mark_t,
|
||||||
|
},
|
||||||
|
#[error("{}:{}: {} {} ({}:{})", mark.line, mark.column, problem, context, context_mark.line, context_mark.column)]
|
||||||
|
ProblemWithContext {
|
||||||
|
context: &'static str,
|
||||||
|
context_mark: yaml_mark_t,
|
||||||
|
problem: &'static str,
|
||||||
|
mark: yaml_mark_t,
|
||||||
|
},
|
||||||
|
#[error(transparent)]
|
||||||
|
Parser(#[from] ParserError),
|
||||||
|
}
|
||||||
|
|
28
src/lib.rs
28
src/lib.rs
|
@ -169,9 +169,7 @@ tie-fighter: '|\-*-/|'
|
||||||
let mut read_in = SANITY_INPUT.as_bytes();
|
let mut read_in = SANITY_INPUT.as_bytes();
|
||||||
yaml_parser_set_input_string(&mut parser, &mut read_in);
|
yaml_parser_set_input_string(&mut parser, &mut read_in);
|
||||||
let mut doc = yaml_document_t::default();
|
let mut doc = yaml_document_t::default();
|
||||||
if yaml_parser_load(&mut parser, &mut doc).is_err() {
|
yaml_parser_load(&mut parser, &mut doc).unwrap();
|
||||||
panic!("parser error: {:?} {:?}", parser.error, parser.problem);
|
|
||||||
}
|
|
||||||
// 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();
|
||||||
|
@ -196,6 +194,22 @@ tie-fighter: '|\-*-/|'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TEST_CASE_QF4Y: &str = r#"[
|
||||||
|
foo: bar
|
||||||
|
]
|
||||||
|
"#;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_case() {
|
||||||
|
let mut parser = parser_new();
|
||||||
|
let mut input = TEST_CASE_QF4Y.as_bytes();
|
||||||
|
yaml_parser_set_input_string(&mut parser, &mut input);
|
||||||
|
let mut doc = yaml_document_t::default();
|
||||||
|
unsafe {
|
||||||
|
yaml_parser_load(&mut parser, &mut doc).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn integration_s7bg() {
|
// fn integration_s7bg() {
|
||||||
// unsafe {
|
// unsafe {
|
||||||
|
@ -288,4 +302,12 @@ tie-fighter: '|\-*-/|'
|
||||||
emitter.assume_init()
|
emitter.assume_init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parser_new<'w>() -> yaml_parser_t<'w> {
|
||||||
|
unsafe {
|
||||||
|
let mut emitter = core::mem::MaybeUninit::uninit();
|
||||||
|
yaml_parser_initialize(emitter.as_mut_ptr()).unwrap();
|
||||||
|
emitter.assume_init()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
230
src/loader.rs
230
src/loader.rs
|
@ -4,8 +4,7 @@ use alloc::{vec, vec::Vec};
|
||||||
use crate::yaml::{YamlEventData, YamlNodeData};
|
use crate::yaml::{YamlEventData, YamlNodeData};
|
||||||
use crate::{
|
use crate::{
|
||||||
libc, yaml_alias_data_t, yaml_document_delete, yaml_document_t, yaml_event_t, yaml_mark_t,
|
libc, yaml_alias_data_t, yaml_document_delete, yaml_document_t, yaml_event_t, yaml_mark_t,
|
||||||
yaml_node_pair_t, yaml_node_t, yaml_parser_parse, yaml_parser_t, YAML_COMPOSER_ERROR,
|
yaml_node_pair_t, yaml_node_t, yaml_parser_parse, yaml_parser_t, ComposerError,
|
||||||
YAML_MEMORY_ERROR,
|
|
||||||
};
|
};
|
||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
|
@ -26,65 +25,71 @@ use core::mem::MaybeUninit;
|
||||||
pub unsafe fn yaml_parser_load(
|
pub unsafe fn yaml_parser_load(
|
||||||
parser: &mut yaml_parser_t,
|
parser: &mut yaml_parser_t,
|
||||||
document: &mut yaml_document_t,
|
document: &mut yaml_document_t,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ComposerError> {
|
||||||
let mut event = yaml_event_t::default();
|
|
||||||
*document = yaml_document_t::default();
|
*document = yaml_document_t::default();
|
||||||
document.nodes.reserve(16);
|
document.nodes.reserve(16);
|
||||||
|
|
||||||
if !parser.stream_start_produced {
|
if !parser.stream_start_produced {
|
||||||
if let Err(()) = yaml_parser_parse(parser, &mut event) {
|
match yaml_parser_parse(parser) {
|
||||||
yaml_parser_delete_aliases(parser);
|
Ok(yaml_event_t {
|
||||||
yaml_document_delete(document);
|
data: YamlEventData::StreamStart { .. },
|
||||||
return Err(());
|
..
|
||||||
} else {
|
}) => (),
|
||||||
if let YamlEventData::StreamStart { .. } = &event.data {
|
Ok(_) => panic!("expected stream start"),
|
||||||
} else {
|
Err(err) => {
|
||||||
panic!("expected stream start");
|
yaml_parser_delete_aliases(parser);
|
||||||
|
yaml_document_delete(document);
|
||||||
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if parser.stream_end_produced {
|
if parser.stream_end_produced {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if let Ok(()) = yaml_parser_parse(parser, &mut event) {
|
let err: ComposerError;
|
||||||
if let YamlEventData::StreamEnd = &event.data {
|
match yaml_parser_parse(parser) {
|
||||||
return Ok(());
|
Ok(event) => {
|
||||||
}
|
if let YamlEventData::StreamEnd = &event.data {
|
||||||
parser.aliases.reserve(16);
|
return Ok(());
|
||||||
if let Ok(()) = yaml_parser_load_document(parser, &mut event, document) {
|
}
|
||||||
yaml_parser_delete_aliases(parser);
|
parser.aliases.reserve(16);
|
||||||
return Ok(());
|
match yaml_parser_load_document(parser, event, document) {
|
||||||
|
Ok(()) => {
|
||||||
|
yaml_parser_delete_aliases(parser);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Err(e) => err = e,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Err(e) => err = e.into(),
|
||||||
}
|
}
|
||||||
yaml_parser_delete_aliases(parser);
|
yaml_parser_delete_aliases(parser);
|
||||||
yaml_document_delete(document);
|
yaml_document_delete(document);
|
||||||
Err(())
|
Err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn yaml_parser_set_composer_error(
|
fn yaml_parser_set_composer_error<T>(
|
||||||
parser: &mut yaml_parser_t,
|
|
||||||
problem: &'static str,
|
problem: &'static str,
|
||||||
problem_mark: yaml_mark_t,
|
problem_mark: yaml_mark_t,
|
||||||
) -> Result<(), ()> {
|
) -> Result<T, ComposerError> {
|
||||||
parser.error = YAML_COMPOSER_ERROR;
|
Err(ComposerError::Problem {
|
||||||
parser.problem = Some(problem);
|
problem,
|
||||||
parser.problem_mark = problem_mark;
|
mark: problem_mark,
|
||||||
Err(())
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn yaml_parser_set_composer_error_context(
|
fn yaml_parser_set_composer_error_context<T>(
|
||||||
parser: &mut yaml_parser_t,
|
|
||||||
context: &'static str,
|
context: &'static str,
|
||||||
context_mark: yaml_mark_t,
|
context_mark: yaml_mark_t,
|
||||||
problem: &'static str,
|
problem: &'static str,
|
||||||
problem_mark: yaml_mark_t,
|
problem_mark: yaml_mark_t,
|
||||||
) -> Result<(), ()> {
|
) -> Result<T, ComposerError> {
|
||||||
parser.error = YAML_COMPOSER_ERROR;
|
Err(ComposerError::ProblemWithContext {
|
||||||
parser.context = Some(context);
|
context,
|
||||||
parser.context_mark = context_mark;
|
context_mark,
|
||||||
parser.problem = Some(problem);
|
problem,
|
||||||
parser.problem_mark = problem_mark;
|
mark: problem_mark,
|
||||||
Err(())
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn yaml_parser_delete_aliases(parser: &mut yaml_parser_t) {
|
unsafe fn yaml_parser_delete_aliases(parser: &mut yaml_parser_t) {
|
||||||
|
@ -93,24 +98,24 @@ unsafe fn yaml_parser_delete_aliases(parser: &mut yaml_parser_t) {
|
||||||
|
|
||||||
unsafe fn yaml_parser_load_document(
|
unsafe fn yaml_parser_load_document(
|
||||||
parser: &mut yaml_parser_t,
|
parser: &mut yaml_parser_t,
|
||||||
event: &mut yaml_event_t,
|
event: yaml_event_t,
|
||||||
document: &mut yaml_document_t,
|
document: &mut yaml_document_t,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ComposerError> {
|
||||||
let mut ctx = vec![];
|
let mut ctx = vec![];
|
||||||
if let YamlEventData::DocumentStart {
|
if let YamlEventData::DocumentStart {
|
||||||
version_directive,
|
version_directive,
|
||||||
tag_directives,
|
tag_directives,
|
||||||
implicit,
|
implicit,
|
||||||
} = &mut event.data
|
} = event.data
|
||||||
{
|
{
|
||||||
document.version_directive = *version_directive;
|
document.version_directive = version_directive;
|
||||||
document.tag_directives = core::mem::take(tag_directives);
|
document.tag_directives = tag_directives;
|
||||||
document.start_implicit = *implicit;
|
document.start_implicit = implicit;
|
||||||
document.start_mark = event.start_mark;
|
document.start_mark = event.start_mark;
|
||||||
ctx.reserve(16);
|
ctx.reserve(16);
|
||||||
if let Err(()) = yaml_parser_load_nodes(parser, document, &mut ctx) {
|
if let Err(err) = yaml_parser_load_nodes(parser, document, &mut ctx) {
|
||||||
ctx.clear();
|
ctx.clear();
|
||||||
return Err(());
|
return Err(err);
|
||||||
}
|
}
|
||||||
ctx.clear();
|
ctx.clear();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -123,40 +128,39 @@ unsafe fn yaml_parser_load_nodes(
|
||||||
parser: &mut yaml_parser_t,
|
parser: &mut yaml_parser_t,
|
||||||
document: &mut yaml_document_t,
|
document: &mut yaml_document_t,
|
||||||
ctx: &mut Vec<libc::c_int>,
|
ctx: &mut Vec<libc::c_int>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ComposerError> {
|
||||||
let mut event = yaml_event_t::default();
|
|
||||||
let end_implicit;
|
let end_implicit;
|
||||||
let end_mark;
|
let end_mark;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
yaml_parser_parse(parser, &mut event)?;
|
let event = yaml_parser_parse(parser)?;
|
||||||
match &event.data {
|
match event.data {
|
||||||
YamlEventData::NoEvent => panic!("empty event"),
|
YamlEventData::NoEvent => panic!("empty event"),
|
||||||
YamlEventData::StreamStart { .. } => panic!("unexpected stream start event"),
|
YamlEventData::StreamStart { .. } => panic!("unexpected stream start event"),
|
||||||
YamlEventData::StreamEnd => panic!("unexpected stream end event"),
|
YamlEventData::StreamEnd => panic!("unexpected stream end event"),
|
||||||
YamlEventData::DocumentStart { .. } => panic!("unexpected document start event"),
|
YamlEventData::DocumentStart { .. } => panic!("unexpected document start event"),
|
||||||
YamlEventData::DocumentEnd { implicit } => {
|
YamlEventData::DocumentEnd { implicit } => {
|
||||||
end_implicit = *implicit;
|
end_implicit = implicit;
|
||||||
end_mark = event.end_mark;
|
end_mark = event.end_mark;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
YamlEventData::Alias { .. } => {
|
YamlEventData::Alias { .. } => {
|
||||||
yaml_parser_load_alias(parser, &mut event, document, ctx)?;
|
yaml_parser_load_alias(parser, event, document, ctx)?;
|
||||||
}
|
}
|
||||||
YamlEventData::Scalar { .. } => {
|
YamlEventData::Scalar { .. } => {
|
||||||
yaml_parser_load_scalar(parser, &mut event, document, ctx)?;
|
yaml_parser_load_scalar(parser, event, document, ctx)?;
|
||||||
}
|
}
|
||||||
YamlEventData::SequenceStart { .. } => {
|
YamlEventData::SequenceStart { .. } => {
|
||||||
yaml_parser_load_sequence(parser, &mut event, document, ctx)?;
|
yaml_parser_load_sequence(parser, event, document, ctx)?;
|
||||||
}
|
}
|
||||||
YamlEventData::SequenceEnd => {
|
YamlEventData::SequenceEnd => {
|
||||||
yaml_parser_load_sequence_end(parser, &mut event, document, ctx)?;
|
yaml_parser_load_sequence_end(parser, event, document, ctx)?;
|
||||||
}
|
}
|
||||||
YamlEventData::MappingStart { .. } => {
|
YamlEventData::MappingStart { .. } => {
|
||||||
yaml_parser_load_mapping(parser, &mut event, document, ctx)?;
|
yaml_parser_load_mapping(parser, event, document, ctx)?;
|
||||||
}
|
}
|
||||||
YamlEventData::MappingEnd => {
|
YamlEventData::MappingEnd => {
|
||||||
yaml_parser_load_mapping_end(parser, &mut event, document, ctx)?;
|
yaml_parser_load_mapping_end(parser, event, document, ctx)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +174,7 @@ unsafe fn yaml_parser_register_anchor(
|
||||||
document: &mut yaml_document_t,
|
document: &mut yaml_document_t,
|
||||||
index: libc::c_int,
|
index: libc::c_int,
|
||||||
anchor: Option<String>,
|
anchor: Option<String>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ComposerError> {
|
||||||
let Some(anchor) = anchor else {
|
let Some(anchor) = anchor else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
@ -182,7 +186,6 @@ unsafe fn yaml_parser_register_anchor(
|
||||||
for alias_data in parser.aliases.iter() {
|
for alias_data in parser.aliases.iter() {
|
||||||
if alias_data.anchor == data.anchor {
|
if alias_data.anchor == data.anchor {
|
||||||
return yaml_parser_set_composer_error_context(
|
return yaml_parser_set_composer_error_context(
|
||||||
parser,
|
|
||||||
"found duplicate anchor; first occurrence",
|
"found duplicate anchor; first occurrence",
|
||||||
alias_data.mark,
|
alias_data.mark,
|
||||||
"second occurrence",
|
"second occurrence",
|
||||||
|
@ -195,11 +198,10 @@ unsafe fn yaml_parser_register_anchor(
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn yaml_parser_load_node_add(
|
unsafe fn yaml_parser_load_node_add(
|
||||||
parser: &mut yaml_parser_t,
|
|
||||||
document: &mut yaml_document_t,
|
document: &mut yaml_document_t,
|
||||||
ctx: &mut Vec<libc::c_int>,
|
ctx: &mut Vec<libc::c_int>,
|
||||||
index: libc::c_int,
|
index: libc::c_int,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ComposerError> {
|
||||||
if ctx.is_empty() {
|
if ctx.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -207,7 +209,6 @@ unsafe fn yaml_parser_load_node_add(
|
||||||
let parent = &mut document.nodes[parent_index as usize - 1];
|
let parent = &mut document.nodes[parent_index as usize - 1];
|
||||||
match parent.data {
|
match parent.data {
|
||||||
YamlNodeData::Sequence { ref mut items, .. } => {
|
YamlNodeData::Sequence { ref mut items, .. } => {
|
||||||
STACK_LIMIT!(parser, items)?;
|
|
||||||
items.push(index);
|
items.push(index);
|
||||||
}
|
}
|
||||||
YamlNodeData::Mapping { ref mut pairs, .. } => {
|
YamlNodeData::Mapping { ref mut pairs, .. } => {
|
||||||
|
@ -224,7 +225,6 @@ unsafe fn yaml_parser_load_node_add(
|
||||||
if do_push {
|
if do_push {
|
||||||
(*pair).key = index;
|
(*pair).key = index;
|
||||||
(*pair).value = 0;
|
(*pair).value = 0;
|
||||||
STACK_LIMIT!(parser, pairs)?;
|
|
||||||
pairs.push(*pair);
|
pairs.push(*pair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,10 +237,10 @@ unsafe fn yaml_parser_load_node_add(
|
||||||
|
|
||||||
unsafe fn yaml_parser_load_alias(
|
unsafe fn yaml_parser_load_alias(
|
||||||
parser: &mut yaml_parser_t,
|
parser: &mut yaml_parser_t,
|
||||||
event: &mut yaml_event_t, // TODO: Take by value
|
event: yaml_event_t,
|
||||||
document: &mut yaml_document_t,
|
document: &mut yaml_document_t,
|
||||||
ctx: &mut Vec<libc::c_int>,
|
ctx: &mut Vec<libc::c_int>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ComposerError> {
|
||||||
let anchor: &str = if let YamlEventData::Alias { anchor } = &event.data {
|
let anchor: &str = if let YamlEventData::Alias { anchor } = &event.data {
|
||||||
&*anchor
|
&*anchor
|
||||||
} else {
|
} else {
|
||||||
|
@ -249,72 +249,64 @@ unsafe fn yaml_parser_load_alias(
|
||||||
|
|
||||||
for alias_data in parser.aliases.iter() {
|
for alias_data in parser.aliases.iter() {
|
||||||
if alias_data.anchor == anchor {
|
if alias_data.anchor == anchor {
|
||||||
return yaml_parser_load_node_add(parser, document, ctx, alias_data.index);
|
return yaml_parser_load_node_add(document, ctx, alias_data.index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
yaml_parser_set_composer_error(parser, "found undefined alias", event.start_mark)
|
yaml_parser_set_composer_error("found undefined alias", event.start_mark)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn yaml_parser_load_scalar(
|
unsafe fn yaml_parser_load_scalar(
|
||||||
parser: &mut yaml_parser_t,
|
parser: &mut yaml_parser_t,
|
||||||
event: &mut yaml_event_t, // TODO: Take by value
|
event: yaml_event_t,
|
||||||
document: &mut yaml_document_t,
|
document: &mut yaml_document_t,
|
||||||
ctx: &mut Vec<libc::c_int>,
|
ctx: &mut Vec<libc::c_int>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ComposerError> {
|
||||||
let (mut tag, value, style, anchor) = if let YamlEventData::Scalar {
|
let YamlEventData::Scalar {
|
||||||
tag,
|
mut tag,
|
||||||
value,
|
value,
|
||||||
style,
|
style,
|
||||||
anchor,
|
anchor,
|
||||||
..
|
..
|
||||||
} = &event.data
|
} = event.data
|
||||||
{
|
else {
|
||||||
(tag.clone(), value, *style, anchor.clone())
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let index: libc::c_int;
|
let index: libc::c_int;
|
||||||
if let Ok(()) = STACK_LIMIT!(parser, document.nodes) {
|
if tag.is_none() || tag.as_deref() == Some("!") {
|
||||||
if tag.is_none() || tag.as_deref() == Some("!") {
|
tag = Some(String::from("tag:yaml.org,2002:str"));
|
||||||
tag = Some(String::from("tag:yaml.org,2002:str"));
|
|
||||||
}
|
|
||||||
let node = yaml_node_t {
|
|
||||||
data: YamlNodeData::Scalar {
|
|
||||||
value: value.clone(), // TODO: move
|
|
||||||
style,
|
|
||||||
},
|
|
||||||
tag,
|
|
||||||
start_mark: (*event).start_mark,
|
|
||||||
end_mark: (*event).end_mark,
|
|
||||||
};
|
|
||||||
document.nodes.push(node);
|
|
||||||
index = document.nodes.len() as libc::c_int;
|
|
||||||
yaml_parser_register_anchor(parser, document, index, anchor)?;
|
|
||||||
return yaml_parser_load_node_add(parser, document, ctx, index);
|
|
||||||
}
|
}
|
||||||
Err(())
|
let node = yaml_node_t {
|
||||||
|
data: YamlNodeData::Scalar { value, style },
|
||||||
|
tag,
|
||||||
|
start_mark: event.start_mark,
|
||||||
|
end_mark: event.end_mark,
|
||||||
|
};
|
||||||
|
document.nodes.push(node);
|
||||||
|
index = document.nodes.len() as libc::c_int;
|
||||||
|
yaml_parser_register_anchor(parser, document, index, anchor)?;
|
||||||
|
yaml_parser_load_node_add(document, ctx, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn yaml_parser_load_sequence(
|
unsafe fn yaml_parser_load_sequence(
|
||||||
parser: &mut yaml_parser_t,
|
parser: &mut yaml_parser_t,
|
||||||
event: &mut yaml_event_t, // TODO: Take by value.
|
event: yaml_event_t,
|
||||||
document: &mut yaml_document_t,
|
document: &mut yaml_document_t,
|
||||||
ctx: &mut Vec<libc::c_int>,
|
ctx: &mut Vec<libc::c_int>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ComposerError> {
|
||||||
let (mut tag, style, anchor) = if let YamlEventData::SequenceStart {
|
let YamlEventData::SequenceStart {
|
||||||
anchor, tag, style, ..
|
anchor,
|
||||||
} = &event.data
|
mut tag,
|
||||||
{
|
style,
|
||||||
(tag.clone(), *style, anchor)
|
..
|
||||||
} else {
|
} = event.data
|
||||||
|
else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut items = Vec::with_capacity(16);
|
let mut items = Vec::with_capacity(16);
|
||||||
let index: libc::c_int;
|
let index: libc::c_int;
|
||||||
STACK_LIMIT!(parser, document.nodes)?;
|
|
||||||
if tag.is_none() || tag.as_deref() == Some("!") {
|
if tag.is_none() || tag.as_deref() == Some("!") {
|
||||||
tag = Some(String::from("tag:yaml.org,2002:seq"));
|
tag = Some(String::from("tag:yaml.org,2002:seq"));
|
||||||
}
|
}
|
||||||
|
@ -332,47 +324,46 @@ unsafe fn yaml_parser_load_sequence(
|
||||||
document.nodes.push(node);
|
document.nodes.push(node);
|
||||||
index = document.nodes.len() as libc::c_int;
|
index = document.nodes.len() as libc::c_int;
|
||||||
yaml_parser_register_anchor(parser, document, index, anchor.clone())?;
|
yaml_parser_register_anchor(parser, document, index, anchor.clone())?;
|
||||||
yaml_parser_load_node_add(parser, document, ctx, index)?;
|
yaml_parser_load_node_add(document, ctx, index)?;
|
||||||
STACK_LIMIT!(parser, *ctx)?;
|
|
||||||
ctx.push(index);
|
ctx.push(index);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn yaml_parser_load_sequence_end(
|
unsafe fn yaml_parser_load_sequence_end(
|
||||||
_parser: &mut yaml_parser_t,
|
_parser: &mut yaml_parser_t,
|
||||||
event: *mut yaml_event_t,
|
event: yaml_event_t,
|
||||||
document: &mut yaml_document_t,
|
document: &mut yaml_document_t,
|
||||||
ctx: &mut Vec<libc::c_int>,
|
ctx: &mut Vec<libc::c_int>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ComposerError> {
|
||||||
__assert!(!ctx.is_empty());
|
__assert!(!ctx.is_empty());
|
||||||
let index: libc::c_int = *ctx.last().unwrap();
|
let index: libc::c_int = *ctx.last().unwrap();
|
||||||
__assert!(matches!(
|
__assert!(matches!(
|
||||||
document.nodes[index as usize - 1].data,
|
document.nodes[index as usize - 1].data,
|
||||||
YamlNodeData::Sequence { .. }
|
YamlNodeData::Sequence { .. }
|
||||||
));
|
));
|
||||||
document.nodes[index as usize - 1].end_mark = (*event).end_mark;
|
document.nodes[index as usize - 1].end_mark = event.end_mark;
|
||||||
_ = ctx.pop();
|
_ = ctx.pop();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn yaml_parser_load_mapping(
|
unsafe fn yaml_parser_load_mapping(
|
||||||
parser: &mut yaml_parser_t,
|
parser: &mut yaml_parser_t,
|
||||||
event: &mut yaml_event_t, // TODO: take by value
|
event: yaml_event_t,
|
||||||
document: &mut yaml_document_t,
|
document: &mut yaml_document_t,
|
||||||
ctx: &mut Vec<libc::c_int>,
|
ctx: &mut Vec<libc::c_int>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ComposerError> {
|
||||||
let (mut tag, style, anchor) = if let YamlEventData::MappingStart {
|
let YamlEventData::MappingStart {
|
||||||
anchor, tag, style, ..
|
anchor,
|
||||||
} = &event.data
|
mut tag,
|
||||||
{
|
style,
|
||||||
(tag.clone(), *style, anchor.clone())
|
..
|
||||||
} else {
|
} = event.data
|
||||||
|
else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut pairs = Vec::with_capacity(16);
|
let mut pairs = Vec::with_capacity(16);
|
||||||
let index: libc::c_int;
|
let index: libc::c_int;
|
||||||
STACK_LIMIT!(parser, document.nodes)?;
|
|
||||||
if tag.is_none() || tag.as_deref() == Some("!") {
|
if tag.is_none() || tag.as_deref() == Some("!") {
|
||||||
tag = Some(String::from("tag:yaml.org,2002:map"));
|
tag = Some(String::from("tag:yaml.org,2002:map"));
|
||||||
}
|
}
|
||||||
|
@ -388,25 +379,24 @@ unsafe fn yaml_parser_load_mapping(
|
||||||
document.nodes.push(node);
|
document.nodes.push(node);
|
||||||
index = document.nodes.len() as libc::c_int;
|
index = document.nodes.len() as libc::c_int;
|
||||||
yaml_parser_register_anchor(parser, document, index, anchor)?;
|
yaml_parser_register_anchor(parser, document, index, anchor)?;
|
||||||
yaml_parser_load_node_add(parser, document, ctx, index)?;
|
yaml_parser_load_node_add(document, ctx, index)?;
|
||||||
STACK_LIMIT!(parser, *ctx)?;
|
|
||||||
ctx.push(index);
|
ctx.push(index);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn yaml_parser_load_mapping_end(
|
unsafe fn yaml_parser_load_mapping_end(
|
||||||
_parser: &mut yaml_parser_t,
|
_parser: &mut yaml_parser_t,
|
||||||
event: *mut yaml_event_t,
|
event: yaml_event_t,
|
||||||
document: &mut yaml_document_t,
|
document: &mut yaml_document_t,
|
||||||
ctx: &mut Vec<libc::c_int>,
|
ctx: &mut Vec<libc::c_int>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ComposerError> {
|
||||||
__assert!(!ctx.is_empty());
|
__assert!(!ctx.is_empty());
|
||||||
let index: libc::c_int = *ctx.last().unwrap();
|
let index: libc::c_int = *ctx.last().unwrap();
|
||||||
__assert!(matches!(
|
__assert!(matches!(
|
||||||
document.nodes[index as usize - 1].data,
|
document.nodes[index as usize - 1].data,
|
||||||
YamlNodeData::Mapping { .. }
|
YamlNodeData::Mapping { .. }
|
||||||
));
|
));
|
||||||
document.nodes[index as usize - 1].end_mark = (*event).end_mark;
|
document.nodes[index as usize - 1].end_mark = event.end_mark;
|
||||||
_ = ctx.pop();
|
_ = ctx.pop();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,17 +268,6 @@ macro_rules! IS_BLANKZ {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! STACK_LIMIT {
|
|
||||||
($context:expr, $stack:expr) => {
|
|
||||||
if $stack.len() < libc::c_int::MAX as usize - 1 {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
(*$context).error = YAML_MEMORY_ERROR;
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn vecdeque_starts_with<T: PartialEq + Copy>(
|
pub(crate) fn vecdeque_starts_with<T: PartialEq + Copy>(
|
||||||
vec: &alloc::collections::VecDeque<T>,
|
vec: &alloc::collections::VecDeque<T>,
|
||||||
needle: &[T],
|
needle: &[T],
|
||||||
|
|
891
src/parser.rs
891
src/parser.rs
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,7 @@ use crate::yaml::{ptrdiff_t, size_t, YamlTokenData};
|
||||||
use crate::{
|
use crate::{
|
||||||
libc, yaml_mark_t, yaml_parser_t, yaml_simple_key_t, yaml_token_t, ReaderError, ScannerError,
|
libc, yaml_mark_t, yaml_parser_t, yaml_simple_key_t, yaml_token_t, ReaderError, ScannerError,
|
||||||
YAML_DOUBLE_QUOTED_SCALAR_STYLE, YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE,
|
YAML_DOUBLE_QUOTED_SCALAR_STYLE, YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE,
|
||||||
YAML_NO_ERROR, YAML_PLAIN_SCALAR_STYLE, YAML_SINGLE_QUOTED_SCALAR_STYLE,
|
YAML_PLAIN_SCALAR_STYLE, YAML_SINGLE_QUOTED_SCALAR_STYLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn CACHE(parser: &mut yaml_parser_t, length: size_t) -> Result<(), ReaderError> {
|
fn CACHE(parser: &mut yaml_parser_t, length: size_t) -> Result<(), ReaderError> {
|
||||||
|
@ -99,28 +99,25 @@ fn READ_LINE_STRING(parser: &mut yaml_parser_t, string: &mut String) {
|
||||||
/// An application must not alternate the calls of yaml_parser_scan() with the
|
/// An application must not alternate the calls of yaml_parser_scan() with the
|
||||||
/// calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break
|
/// calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break
|
||||||
/// the parser.
|
/// the parser.
|
||||||
pub fn yaml_parser_scan(
|
pub fn yaml_parser_scan(parser: &mut yaml_parser_t) -> Result<yaml_token_t, ScannerError> {
|
||||||
parser: &mut yaml_parser_t,
|
if parser.stream_end_produced {
|
||||||
token: &mut yaml_token_t,
|
return Ok(yaml_token_t {
|
||||||
) -> Result<(), ScannerError> {
|
data: YamlTokenData::StreamEnd,
|
||||||
*token = yaml_token_t::default();
|
..Default::default()
|
||||||
if parser.stream_end_produced || parser.error != YAML_NO_ERROR {
|
});
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
if !parser.token_available {
|
if !parser.token_available {
|
||||||
yaml_parser_fetch_more_tokens(parser)?;
|
yaml_parser_fetch_more_tokens(parser)?;
|
||||||
}
|
}
|
||||||
if let Some(popped) = parser.tokens.pop_front() {
|
if let Some(token) = parser.tokens.pop_front() {
|
||||||
*token = popped;
|
|
||||||
parser.token_available = false;
|
parser.token_available = false;
|
||||||
parser.tokens_parsed = parser.tokens_parsed.force_add(1);
|
parser.tokens_parsed = parser.tokens_parsed.force_add(1);
|
||||||
if let YamlTokenData::StreamEnd = &(*token).data {
|
if let YamlTokenData::StreamEnd = &token.data {
|
||||||
parser.stream_end_produced = true;
|
parser.stream_end_produced = true;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(token)
|
||||||
} else {
|
} else {
|
||||||
// token_available should have been false
|
unreachable!("no more tokens, but stream-end was not produced")
|
||||||
unreachable!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
src/yaml.rs
21
src/yaml.rs
|
@ -670,20 +670,6 @@ pub struct yaml_alias_data_t {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct yaml_parser_t<'r> {
|
pub struct yaml_parser_t<'r> {
|
||||||
/// Error type.
|
|
||||||
pub error: yaml_error_type_t,
|
|
||||||
/// Error description.
|
|
||||||
pub problem: Option<&'static str>,
|
|
||||||
/// The byte about which the problem occured.
|
|
||||||
pub problem_offset: size_t,
|
|
||||||
/// The problematic value (-1 is none).
|
|
||||||
pub problem_value: libc::c_int,
|
|
||||||
/// The problem position.
|
|
||||||
pub problem_mark: yaml_mark_t,
|
|
||||||
/// The error context.
|
|
||||||
pub context: Option<&'static str>,
|
|
||||||
/// The context position.
|
|
||||||
pub context_mark: yaml_mark_t,
|
|
||||||
/// Read handler.
|
/// Read handler.
|
||||||
pub(crate) read_handler: Option<&'r mut dyn std::io::Read>,
|
pub(crate) read_handler: Option<&'r mut dyn std::io::Read>,
|
||||||
/// Standard (string or file) input data.
|
/// Standard (string or file) input data.
|
||||||
|
@ -743,13 +729,6 @@ pub struct yaml_parser_t<'r> {
|
||||||
impl<'r> Default for yaml_parser_t<'r> {
|
impl<'r> Default for yaml_parser_t<'r> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
error: Default::default(),
|
|
||||||
problem: Default::default(),
|
|
||||||
problem_offset: Default::default(),
|
|
||||||
problem_value: Default::default(),
|
|
||||||
problem_mark: Default::default(),
|
|
||||||
context: Default::default(),
|
|
||||||
context_mark: Default::default(),
|
|
||||||
read_handler: None,
|
read_handler: None,
|
||||||
input: Default::default(),
|
input: Default::default(),
|
||||||
eof: Default::default(),
|
eof: Default::default(),
|
||||||
|
|
Loading…
Reference in a new issue