mirror of
https://github.com/simonask/libyaml-safer
synced 2024-11-24 12:23:02 +00:00
Box errors, remove thiserror
This commit is contained in:
parent
8f6ce4bf4a
commit
4f9ef3221e
8 changed files with 456 additions and 399 deletions
|
@ -20,9 +20,6 @@ unsafe-libyaml-test-suite = { path = "tests/data" }
|
|||
[lib]
|
||||
doc-scrape-examples = false
|
||||
|
||||
[dependencies]
|
||||
thiserror = "1.0"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
|
|
@ -45,10 +45,6 @@ errors may be reported with reduced fidelity compared with libyaml (e.g., error
|
|||
messages may look slightly different), but the same inputs should generate the
|
||||
same general errors.
|
||||
|
||||
This library introduces no new dependencies except for
|
||||
[`thiserror`](https://docs.rs/thiserror) for convenience. This dependency may go
|
||||
away in the future.
|
||||
|
||||
### Compatibility and interoperability
|
||||
|
||||
While this library matches the behavior of libyaml, it is not intended as a
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
AliasData, Anchors, ComposerError, Emitter, EmitterError, Event, EventData, MappingStyle, Mark,
|
||||
Parser, ScalarStyle, SequenceStyle, TagDirective, VersionDirective, DEFAULT_MAPPING_TAG,
|
||||
AliasData, Anchors, Emitter, Error, Event, EventData, MappingStyle, Mark, Parser, Result,
|
||||
ScalarStyle, SequenceStyle, TagDirective, VersionDirective, DEFAULT_MAPPING_TAG,
|
||||
DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG,
|
||||
};
|
||||
|
||||
|
@ -249,7 +249,7 @@ impl Document {
|
|||
///
|
||||
/// An application must not alternate the calls of [`Document::load()`] with
|
||||
/// the calls of [`Parser::parse()`]. Doing this will break the parser.
|
||||
pub fn load(parser: &mut Parser) -> Result<Document, ComposerError> {
|
||||
pub fn load(parser: &mut Parser) -> Result<Document> {
|
||||
let mut document = Document::new(None, &[], false, false);
|
||||
document.nodes.reserve(16);
|
||||
|
||||
|
@ -262,14 +262,14 @@ impl Document {
|
|||
Ok(_) => panic!("expected stream start"),
|
||||
Err(err) => {
|
||||
parser.delete_aliases();
|
||||
return Err(err.into());
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
if parser.scanner.stream_end_produced {
|
||||
return Ok(document);
|
||||
}
|
||||
let err: ComposerError;
|
||||
let err: Error;
|
||||
match parser.parse() {
|
||||
Ok(event) => {
|
||||
if let EventData::StreamEnd = &event.data {
|
||||
|
@ -284,37 +284,13 @@ impl Document {
|
|||
Err(e) => err = e,
|
||||
}
|
||||
}
|
||||
Err(e) => err = e.into(),
|
||||
Err(e) => err = e,
|
||||
}
|
||||
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> {
|
||||
fn load_document(&mut self, parser: &mut Parser, event: Event) -> Result<()> {
|
||||
let mut ctx = vec![];
|
||||
if let EventData::DocumentStart {
|
||||
version_directive,
|
||||
|
@ -338,7 +314,7 @@ impl Document {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_nodes(&mut self, parser: &mut Parser, ctx: &mut Vec<i32>) -> Result<(), ComposerError> {
|
||||
fn load_nodes(&mut self, parser: &mut Parser, ctx: &mut Vec<i32>) -> Result<()> {
|
||||
let end_implicit;
|
||||
let end_mark;
|
||||
|
||||
|
@ -383,7 +359,7 @@ impl Document {
|
|||
parser: &mut Parser,
|
||||
index: i32,
|
||||
anchor: Option<String>,
|
||||
) -> Result<(), ComposerError> {
|
||||
) -> Result<()> {
|
||||
let Some(anchor) = anchor else {
|
||||
return Ok(());
|
||||
};
|
||||
|
@ -394,19 +370,19 @@ impl Document {
|
|||
};
|
||||
for alias_data in &parser.aliases {
|
||||
if alias_data.anchor == data.anchor {
|
||||
return Self::set_composer_error_context(
|
||||
return Err(Error::composer(
|
||||
"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> {
|
||||
fn load_node_add(&mut self, ctx: &[i32], index: i32) -> Result<()> {
|
||||
if ctx.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -439,12 +415,7 @@ impl Document {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn load_alias(
|
||||
&mut self,
|
||||
parser: &mut Parser,
|
||||
event: Event,
|
||||
ctx: &[i32],
|
||||
) -> Result<(), ComposerError> {
|
||||
fn load_alias(&mut self, parser: &mut Parser, event: Event, ctx: &[i32]) -> Result<()> {
|
||||
let EventData::Alias { anchor } = &event.data else {
|
||||
unreachable!()
|
||||
};
|
||||
|
@ -455,15 +426,15 @@ impl Document {
|
|||
}
|
||||
}
|
||||
|
||||
Self::set_composer_error("found undefined alias", event.start_mark)
|
||||
Err(Error::composer(
|
||||
"",
|
||||
Mark::default(),
|
||||
"found undefined alias",
|
||||
event.start_mark,
|
||||
))
|
||||
}
|
||||
|
||||
fn load_scalar(
|
||||
&mut self,
|
||||
parser: &mut Parser,
|
||||
event: Event,
|
||||
ctx: &[i32],
|
||||
) -> Result<(), ComposerError> {
|
||||
fn load_scalar(&mut self, parser: &mut Parser, event: Event, ctx: &[i32]) -> Result<()> {
|
||||
let EventData::Scalar {
|
||||
mut tag,
|
||||
value,
|
||||
|
@ -495,7 +466,7 @@ impl Document {
|
|||
parser: &mut Parser,
|
||||
event: Event,
|
||||
ctx: &mut Vec<i32>,
|
||||
) -> Result<(), ComposerError> {
|
||||
) -> Result<()> {
|
||||
let EventData::SequenceStart {
|
||||
anchor,
|
||||
mut tag,
|
||||
|
@ -530,7 +501,7 @@ impl Document {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn load_sequence_end(&mut self, event: Event, ctx: &mut Vec<i32>) -> Result<(), ComposerError> {
|
||||
fn load_sequence_end(&mut self, event: Event, ctx: &mut Vec<i32>) -> Result<()> {
|
||||
assert!(!ctx.is_empty());
|
||||
let index: i32 = *ctx.last().unwrap();
|
||||
assert!(matches!(
|
||||
|
@ -547,7 +518,7 @@ impl Document {
|
|||
parser: &mut Parser,
|
||||
event: Event,
|
||||
ctx: &mut Vec<i32>,
|
||||
) -> Result<(), ComposerError> {
|
||||
) -> Result<()> {
|
||||
let EventData::MappingStart {
|
||||
anchor,
|
||||
mut tag,
|
||||
|
@ -580,7 +551,7 @@ impl Document {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn load_mapping_end(&mut self, event: Event, ctx: &mut Vec<i32>) -> Result<(), ComposerError> {
|
||||
fn load_mapping_end(&mut self, event: Event, ctx: &mut Vec<i32>) -> Result<()> {
|
||||
assert!(!ctx.is_empty());
|
||||
let index: i32 = *ctx.last().unwrap();
|
||||
assert!(matches!(
|
||||
|
@ -596,7 +567,7 @@ impl Document {
|
|||
///
|
||||
/// The document object may be generated using the [`Document::load()`]
|
||||
/// function or the [`Document::new()`] function.
|
||||
pub fn dump(mut self, emitter: &mut Emitter) -> Result<(), EmitterError> {
|
||||
pub fn dump(mut self, emitter: &mut Emitter) -> Result<()> {
|
||||
if !emitter.opened {
|
||||
if let Err(err) = emitter.open() {
|
||||
emitter.reset_anchors();
|
||||
|
@ -651,7 +622,7 @@ impl Document {
|
|||
}
|
||||
}
|
||||
|
||||
fn dump_node(&mut self, emitter: &mut Emitter, index: i32) -> Result<(), EmitterError> {
|
||||
fn dump_node(&mut self, emitter: &mut Emitter, index: i32) -> Result<()> {
|
||||
let node = &mut self.nodes[index as usize - 1];
|
||||
let anchor_id: i32 = emitter.anchors[index as usize - 1].anchor;
|
||||
let mut anchor: Option<String> = None;
|
||||
|
@ -672,16 +643,12 @@ impl Document {
|
|||
}
|
||||
}
|
||||
|
||||
fn dump_alias(emitter: &mut Emitter, anchor: String) -> Result<(), EmitterError> {
|
||||
fn dump_alias(emitter: &mut Emitter, anchor: String) -> Result<()> {
|
||||
let event = Event::new(EventData::Alias { anchor });
|
||||
emitter.emit(event)
|
||||
}
|
||||
|
||||
fn dump_scalar(
|
||||
emitter: &mut Emitter,
|
||||
node: Node,
|
||||
anchor: Option<String>,
|
||||
) -> Result<(), EmitterError> {
|
||||
fn dump_scalar(emitter: &mut Emitter, node: Node, anchor: Option<String>) -> Result<()> {
|
||||
let plain_implicit = node.tag.as_deref() == Some(DEFAULT_SCALAR_TAG);
|
||||
let quoted_implicit = node.tag.as_deref() == Some(DEFAULT_SCALAR_TAG); // TODO: Why compare twice?! (even the C code does this)
|
||||
|
||||
|
@ -704,7 +671,7 @@ impl Document {
|
|||
emitter: &mut Emitter,
|
||||
node: Node,
|
||||
anchor: Option<String>,
|
||||
) -> Result<(), EmitterError> {
|
||||
) -> Result<()> {
|
||||
let implicit = node.tag.as_deref() == Some(DEFAULT_SEQUENCE_TAG);
|
||||
|
||||
let NodeData::Sequence { items, style } = node.data else {
|
||||
|
@ -730,7 +697,7 @@ impl Document {
|
|||
emitter: &mut Emitter,
|
||||
node: Node,
|
||||
anchor: Option<String>,
|
||||
) -> Result<(), EmitterError> {
|
||||
) -> Result<()> {
|
||||
let implicit = node.tag.as_deref() == Some(DEFAULT_MAPPING_TAG);
|
||||
|
||||
let NodeData::Mapping { pairs, style } = node.data else {
|
||||
|
|
186
src/emitter.rs
186
src/emitter.rs
|
@ -6,8 +6,8 @@ use crate::macros::{
|
|||
is_alpha, is_ascii, is_blank, is_blankz, is_bom, is_break, is_breakz, is_printable, is_space,
|
||||
};
|
||||
use crate::{
|
||||
Break, EmitterError, Encoding, Event, EventData, MappingStyle, ScalarStyle, SequenceStyle,
|
||||
TagDirective, VersionDirective, WriterError, OUTPUT_BUFFER_SIZE,
|
||||
Break, Encoding, Error, Event, EventData, MappingStyle, Result, ScalarStyle, SequenceStyle,
|
||||
TagDirective, VersionDirective, OUTPUT_BUFFER_SIZE,
|
||||
};
|
||||
|
||||
/// The emitter structure.
|
||||
|
@ -176,10 +176,6 @@ struct ScalarAnalysis<'a> {
|
|||
}
|
||||
|
||||
impl<'w> Emitter<'w> {
|
||||
fn set_emitter_error<T>(problem: &'static str) -> Result<T, EmitterError> {
|
||||
Err(EmitterError::Problem(problem))
|
||||
}
|
||||
|
||||
/// Create an self.
|
||||
pub fn new() -> Emitter<'w> {
|
||||
Emitter {
|
||||
|
@ -224,7 +220,7 @@ impl<'w> Emitter<'w> {
|
|||
///
|
||||
/// This function should be used before
|
||||
/// [`Document::dump()`](crate::Document::dump) is called.
|
||||
pub fn open(&mut self) -> Result<(), EmitterError> {
|
||||
pub fn open(&mut self) -> Result<()> {
|
||||
assert!(!self.opened);
|
||||
let event = Event::stream_start(Encoding::Any);
|
||||
self.emit(event)?;
|
||||
|
@ -236,7 +232,7 @@ impl<'w> Emitter<'w> {
|
|||
///
|
||||
/// This function should be used after
|
||||
/// [`Document::dump()`](crate::Document::dump) is called.
|
||||
pub fn close(&mut self) -> Result<(), EmitterError> {
|
||||
pub fn close(&mut self) -> Result<()> {
|
||||
assert!(self.opened);
|
||||
if self.closed {
|
||||
return Ok(());
|
||||
|
@ -305,7 +301,7 @@ impl<'w> Emitter<'w> {
|
|||
/// [`Parser::parse()`](crate::Parser::parse) function. The emitter takes
|
||||
/// the responsibility for the event object and destroys its content after
|
||||
/// it is emitted. The event object is destroyed even if the function fails.
|
||||
pub fn emit(&mut self, event: Event) -> Result<(), EmitterError> {
|
||||
pub fn emit(&mut self, event: Event) -> Result<()> {
|
||||
self.events.push_back(event);
|
||||
while let Some(event) = self.needs_mode_events() {
|
||||
let tag_directives = core::mem::take(&mut self.tag_directives);
|
||||
|
@ -323,7 +319,7 @@ impl<'w> Emitter<'w> {
|
|||
}
|
||||
|
||||
/// Equivalent of the libyaml `FLUSH` macro.
|
||||
fn flush_if_needed(&mut self) -> Result<(), WriterError> {
|
||||
fn flush_if_needed(&mut self) -> Result<()> {
|
||||
if self.buffer.len() < OUTPUT_BUFFER_SIZE - 5 {
|
||||
Ok(())
|
||||
} else {
|
||||
|
@ -332,7 +328,7 @@ impl<'w> Emitter<'w> {
|
|||
}
|
||||
|
||||
/// Equivalent of the libyaml `PUT` macro.
|
||||
fn put(&mut self, value: char) -> Result<(), WriterError> {
|
||||
fn put(&mut self, value: char) -> Result<()> {
|
||||
self.flush_if_needed()?;
|
||||
self.buffer.push(value);
|
||||
self.column += 1;
|
||||
|
@ -340,7 +336,7 @@ impl<'w> Emitter<'w> {
|
|||
}
|
||||
|
||||
/// Equivalent of the libyaml `PUT_BREAK` macro.
|
||||
fn put_break(&mut self) -> Result<(), WriterError> {
|
||||
fn put_break(&mut self) -> Result<()> {
|
||||
self.flush_if_needed()?;
|
||||
if self.line_break == Break::Cr {
|
||||
self.buffer.push('\r');
|
||||
|
@ -357,7 +353,7 @@ impl<'w> Emitter<'w> {
|
|||
/// Write UTF-8 charanters from `string` to `emitter` and increment
|
||||
/// `emitter.column` the appropriate number of times. It is assumed that the
|
||||
/// string does not contain line breaks!
|
||||
fn write_str(&mut self, string: &str) -> Result<(), WriterError> {
|
||||
fn write_str(&mut self, string: &str) -> Result<()> {
|
||||
if self.buffer.len() + string.len() > OUTPUT_BUFFER_SIZE {
|
||||
self.flush()?;
|
||||
}
|
||||
|
@ -376,7 +372,7 @@ impl<'w> Emitter<'w> {
|
|||
}
|
||||
|
||||
/// Equivalent of the libyaml `WRITE` macro.
|
||||
fn write_char(&mut self, ch: char) -> Result<(), WriterError> {
|
||||
fn write_char(&mut self, ch: char) -> Result<()> {
|
||||
self.flush_if_needed()?;
|
||||
self.buffer.push(ch);
|
||||
self.column += 1;
|
||||
|
@ -384,7 +380,7 @@ impl<'w> Emitter<'w> {
|
|||
}
|
||||
|
||||
/// Equivalent of the libyaml `WRITE_BREAK` macro.
|
||||
fn write_break(&mut self, ch: char) -> Result<(), WriterError> {
|
||||
fn write_break(&mut self, ch: char) -> Result<()> {
|
||||
self.flush_if_needed()?;
|
||||
if ch == '\n' {
|
||||
self.put_break()?;
|
||||
|
@ -437,17 +433,13 @@ impl<'w> Emitter<'w> {
|
|||
None
|
||||
}
|
||||
|
||||
fn append_tag_directive(
|
||||
&mut self,
|
||||
value: TagDirective,
|
||||
allow_duplicates: bool,
|
||||
) -> Result<(), EmitterError> {
|
||||
fn append_tag_directive(&mut self, value: TagDirective, allow_duplicates: bool) -> Result<()> {
|
||||
for tag_directive in &self.tag_directives {
|
||||
if value.handle == tag_directive.handle {
|
||||
if allow_duplicates {
|
||||
return Ok(());
|
||||
}
|
||||
return Self::set_emitter_error("duplicate %TAG directive");
|
||||
return Err(Error::emitter("duplicate %TAG directive"));
|
||||
}
|
||||
}
|
||||
self.tag_directives.push(value);
|
||||
|
@ -463,11 +455,7 @@ impl<'w> Emitter<'w> {
|
|||
}
|
||||
}
|
||||
|
||||
fn state_machine<'a>(
|
||||
&mut self,
|
||||
event: &'a Event,
|
||||
analysis: &mut Analysis<'a>,
|
||||
) -> Result<(), EmitterError> {
|
||||
fn state_machine<'a>(&mut self, event: &'a Event, analysis: &mut Analysis<'a>) -> Result<()> {
|
||||
match self.state {
|
||||
EmitterState::StreamStart => self.emit_stream_start(event),
|
||||
EmitterState::FirstDocumentStart => self.emit_document_start(event, true),
|
||||
|
@ -500,11 +488,11 @@ impl<'w> Emitter<'w> {
|
|||
EmitterState::BlockMappingValue => {
|
||||
self.emit_block_mapping_value(event, false, analysis)
|
||||
}
|
||||
EmitterState::End => Self::set_emitter_error("expected nothing after STREAM-END"),
|
||||
EmitterState::End => Err(Error::emitter("expected nothing after STREAM-END")),
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_stream_start(&mut self, event: &Event) -> Result<(), EmitterError> {
|
||||
fn emit_stream_start(&mut self, event: &Event) -> Result<()> {
|
||||
self.open_ended = 0;
|
||||
if let EventData::StreamStart { ref encoding } = event.data {
|
||||
if self.encoding == Encoding::Any {
|
||||
|
@ -536,10 +524,10 @@ impl<'w> Emitter<'w> {
|
|||
self.state = EmitterState::FirstDocumentStart;
|
||||
return Ok(());
|
||||
}
|
||||
Self::set_emitter_error("expected STREAM-START")
|
||||
Err(Error::emitter("expected STREAM-START"))
|
||||
}
|
||||
|
||||
fn emit_document_start(&mut self, event: &Event, first: bool) -> Result<(), EmitterError> {
|
||||
fn emit_document_start(&mut self, event: &Event, first: bool) -> Result<()> {
|
||||
if let EventData::DocumentStart {
|
||||
version_directive,
|
||||
tag_directives,
|
||||
|
@ -619,19 +607,15 @@ impl<'w> Emitter<'w> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
Self::set_emitter_error("expected DOCUMENT-START or STREAM-END")
|
||||
Err(Error::emitter("expected DOCUMENT-START or STREAM-END"))
|
||||
}
|
||||
|
||||
fn emit_document_content(
|
||||
&mut self,
|
||||
event: &Event,
|
||||
analysis: &mut Analysis,
|
||||
) -> Result<(), EmitterError> {
|
||||
fn emit_document_content(&mut self, event: &Event, analysis: &mut Analysis) -> Result<()> {
|
||||
self.states.push(EmitterState::DocumentEnd);
|
||||
self.emit_node(event, true, false, false, false, analysis)
|
||||
}
|
||||
|
||||
fn emit_document_end(&mut self, event: &Event) -> Result<(), EmitterError> {
|
||||
fn emit_document_end(&mut self, event: &Event) -> Result<()> {
|
||||
if let EventData::DocumentEnd { implicit } = &event.data {
|
||||
let implicit = *implicit;
|
||||
self.write_indent()?;
|
||||
|
@ -648,7 +632,7 @@ impl<'w> Emitter<'w> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
Self::set_emitter_error("expected DOCUMENT-END")
|
||||
Err(Error::emitter("expected DOCUMENT-END"))
|
||||
}
|
||||
|
||||
fn emit_flow_sequence_item(
|
||||
|
@ -656,7 +640,7 @@ impl<'w> Emitter<'w> {
|
|||
event: &Event,
|
||||
first: bool,
|
||||
analysis: &mut Analysis,
|
||||
) -> Result<(), EmitterError> {
|
||||
) -> Result<()> {
|
||||
if first {
|
||||
self.write_indicator("[", true, true, false)?;
|
||||
self.increase_indent(true, false);
|
||||
|
@ -688,7 +672,7 @@ impl<'w> Emitter<'w> {
|
|||
event: &Event,
|
||||
first: bool,
|
||||
analysis: &mut Analysis,
|
||||
) -> Result<(), EmitterError> {
|
||||
) -> Result<()> {
|
||||
if first {
|
||||
self.write_indicator("{", true, true, false)?;
|
||||
self.increase_indent(true, false);
|
||||
|
@ -727,7 +711,7 @@ impl<'w> Emitter<'w> {
|
|||
event: &Event,
|
||||
simple: bool,
|
||||
analysis: &mut Analysis,
|
||||
) -> Result<(), EmitterError> {
|
||||
) -> Result<()> {
|
||||
if simple {
|
||||
self.write_indicator(":", false, false, false)?;
|
||||
} else {
|
||||
|
@ -745,7 +729,7 @@ impl<'w> Emitter<'w> {
|
|||
event: &Event,
|
||||
first: bool,
|
||||
analysis: &mut Analysis,
|
||||
) -> Result<(), EmitterError> {
|
||||
) -> Result<()> {
|
||||
if first {
|
||||
self.increase_indent(false, self.mapping_context && !self.indention);
|
||||
}
|
||||
|
@ -765,7 +749,7 @@ impl<'w> Emitter<'w> {
|
|||
event: &Event,
|
||||
first: bool,
|
||||
analysis: &mut Analysis,
|
||||
) -> Result<(), EmitterError> {
|
||||
) -> Result<()> {
|
||||
if first {
|
||||
self.increase_indent(false, false);
|
||||
}
|
||||
|
@ -790,7 +774,7 @@ impl<'w> Emitter<'w> {
|
|||
event: &Event,
|
||||
simple: bool,
|
||||
analysis: &mut Analysis,
|
||||
) -> Result<(), EmitterError> {
|
||||
) -> Result<()> {
|
||||
if simple {
|
||||
self.write_indicator(":", false, false, false)?;
|
||||
} else {
|
||||
|
@ -809,7 +793,7 @@ impl<'w> Emitter<'w> {
|
|||
mapping: bool,
|
||||
simple_key: bool,
|
||||
analysis: &mut Analysis,
|
||||
) -> Result<(), EmitterError> {
|
||||
) -> Result<()> {
|
||||
self.root_context = root;
|
||||
self.sequence_context = sequence;
|
||||
self.mapping_context = mapping;
|
||||
|
@ -820,17 +804,13 @@ impl<'w> Emitter<'w> {
|
|||
EventData::Scalar { .. } => self.emit_scalar(event, analysis),
|
||||
EventData::SequenceStart { .. } => self.emit_sequence_start(event, analysis),
|
||||
EventData::MappingStart { .. } => self.emit_mapping_start(event, analysis),
|
||||
_ => {
|
||||
Self::set_emitter_error("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS")
|
||||
}
|
||||
_ => Err(Error::emitter(
|
||||
"expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_alias(
|
||||
&mut self,
|
||||
_event: &Event,
|
||||
analysis: &Option<AnchorAnalysis>,
|
||||
) -> Result<(), EmitterError> {
|
||||
fn emit_alias(&mut self, _event: &Event, analysis: &Option<AnchorAnalysis>) -> Result<()> {
|
||||
self.process_anchor(analysis)?;
|
||||
if self.simple_key_context {
|
||||
self.put(' ')?;
|
||||
|
@ -839,7 +819,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_scalar(&mut self, event: &Event, analysis: &mut Analysis) -> Result<(), EmitterError> {
|
||||
fn emit_scalar(&mut self, event: &Event, analysis: &mut Analysis) -> Result<()> {
|
||||
let Analysis {
|
||||
anchor,
|
||||
tag,
|
||||
|
@ -859,11 +839,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_sequence_start(
|
||||
&mut self,
|
||||
event: &Event,
|
||||
analysis: &Analysis,
|
||||
) -> Result<(), EmitterError> {
|
||||
fn emit_sequence_start(&mut self, event: &Event, analysis: &Analysis) -> Result<()> {
|
||||
let Analysis { anchor, tag, .. } = analysis;
|
||||
self.process_anchor(anchor)?;
|
||||
self.process_tag(tag)?;
|
||||
|
@ -884,11 +860,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_mapping_start(
|
||||
&mut self,
|
||||
event: &Event,
|
||||
analysis: &Analysis,
|
||||
) -> Result<(), EmitterError> {
|
||||
fn emit_mapping_start(&mut self, event: &Event, analysis: &Analysis) -> Result<()> {
|
||||
let Analysis { anchor, tag, .. } = analysis;
|
||||
self.process_anchor(anchor)?;
|
||||
self.process_tag(tag)?;
|
||||
|
@ -980,7 +952,7 @@ impl<'w> Emitter<'w> {
|
|||
event: &Event,
|
||||
scalar_analysis: &mut ScalarAnalysis,
|
||||
tag_analysis: &mut Option<TagAnalysis>,
|
||||
) -> Result<(), EmitterError> {
|
||||
) -> Result<()> {
|
||||
let EventData::Scalar {
|
||||
plain_implicit,
|
||||
quoted_implicit,
|
||||
|
@ -994,7 +966,9 @@ impl<'w> Emitter<'w> {
|
|||
let mut style: ScalarStyle = *style;
|
||||
let no_tag = tag_analysis.is_none();
|
||||
if no_tag && !*plain_implicit && !*quoted_implicit {
|
||||
Self::set_emitter_error("neither tag nor implicit flags are specified")?;
|
||||
return Err(Error::emitter(
|
||||
"neither tag nor implicit flags are specified",
|
||||
));
|
||||
}
|
||||
if style == ScalarStyle::Any {
|
||||
style = ScalarStyle::Plain;
|
||||
|
@ -1037,7 +1011,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn process_anchor(&mut self, analysis: &Option<AnchorAnalysis>) -> Result<(), EmitterError> {
|
||||
fn process_anchor(&mut self, analysis: &Option<AnchorAnalysis>) -> Result<()> {
|
||||
let Some(analysis) = analysis.as_ref() else {
|
||||
return Ok(());
|
||||
};
|
||||
|
@ -1045,7 +1019,7 @@ impl<'w> Emitter<'w> {
|
|||
self.write_anchor(analysis.anchor)
|
||||
}
|
||||
|
||||
fn process_tag(&mut self, analysis: &Option<TagAnalysis>) -> Result<(), EmitterError> {
|
||||
fn process_tag(&mut self, analysis: &Option<TagAnalysis>) -> Result<()> {
|
||||
let Some(analysis) = analysis.as_ref() else {
|
||||
return Ok(());
|
||||
};
|
||||
|
@ -1066,7 +1040,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn process_scalar(&mut self, analysis: &ScalarAnalysis) -> Result<(), EmitterError> {
|
||||
fn process_scalar(&mut self, analysis: &ScalarAnalysis) -> Result<()> {
|
||||
match analysis.style {
|
||||
ScalarStyle::Plain => self.write_plain_scalar(analysis.value, !self.simple_key_context),
|
||||
ScalarStyle::SingleQuoted => {
|
||||
|
@ -1081,59 +1055,59 @@ impl<'w> Emitter<'w> {
|
|||
}
|
||||
}
|
||||
|
||||
fn analyze_version_directive(version_directive: VersionDirective) -> Result<(), EmitterError> {
|
||||
fn analyze_version_directive(version_directive: VersionDirective) -> Result<()> {
|
||||
if version_directive.major != 1
|
||||
|| version_directive.minor != 1 && version_directive.minor != 2
|
||||
{
|
||||
return Self::set_emitter_error("incompatible %YAML directive");
|
||||
return Err(Error::emitter("incompatible %YAML directive"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn analyze_tag_directive(tag_directive: &TagDirective) -> Result<(), EmitterError> {
|
||||
fn analyze_tag_directive(tag_directive: &TagDirective) -> Result<()> {
|
||||
if tag_directive.handle.is_empty() {
|
||||
return Self::set_emitter_error("tag handle must not be empty");
|
||||
return Err(Error::emitter("tag handle must not be empty"));
|
||||
}
|
||||
if !tag_directive.handle.starts_with('!') {
|
||||
return Self::set_emitter_error("tag handle must start with '!'");
|
||||
return Err(Error::emitter("tag handle must start with '!'"));
|
||||
}
|
||||
if !tag_directive.handle.ends_with('!') {
|
||||
return Self::set_emitter_error("tag handle must end with '!'");
|
||||
return Err(Error::emitter("tag handle must end with '!'"));
|
||||
}
|
||||
if tag_directive.handle.len() > 2 {
|
||||
let tag_content = &tag_directive.handle[1..tag_directive.handle.len() - 1];
|
||||
for ch in tag_content.chars() {
|
||||
if !is_alpha(ch) {
|
||||
return Self::set_emitter_error(
|
||||
return Err(Error::emitter(
|
||||
"tag handle must contain alphanumerical characters only",
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if tag_directive.prefix.is_empty() {
|
||||
return Self::set_emitter_error("tag prefix must not be empty");
|
||||
return Err(Error::emitter("tag prefix must not be empty"));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn analyze_anchor(anchor: &str, alias: bool) -> Result<AnchorAnalysis<'_>, EmitterError> {
|
||||
fn analyze_anchor(anchor: &str, alias: bool) -> Result<AnchorAnalysis<'_>> {
|
||||
if anchor.is_empty() {
|
||||
Self::set_emitter_error(if alias {
|
||||
return Err(Error::emitter(if alias {
|
||||
"alias value must not be empty"
|
||||
} else {
|
||||
"anchor value must not be empty"
|
||||
})?;
|
||||
}));
|
||||
}
|
||||
|
||||
for ch in anchor.chars() {
|
||||
if !is_alpha(ch) {
|
||||
Self::set_emitter_error(if alias {
|
||||
return Err(Error::emitter(if alias {
|
||||
"alias value must contain alphanumerical characters only"
|
||||
} else {
|
||||
"anchor value must contain alphanumerical characters only"
|
||||
})?;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1143,9 +1117,9 @@ impl<'w> Emitter<'w> {
|
|||
fn analyze_tag<'a>(
|
||||
tag: &'a str,
|
||||
tag_directives: &'a [TagDirective],
|
||||
) -> Result<TagAnalysis<'a>, EmitterError> {
|
||||
) -> Result<TagAnalysis<'a>> {
|
||||
if tag.is_empty() {
|
||||
Self::set_emitter_error("tag value must not be empty")?;
|
||||
return Err(Error::emitter("tag value must not be empty"));
|
||||
}
|
||||
|
||||
let mut handle = "";
|
||||
|
@ -1163,7 +1137,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(TagAnalysis { handle, suffix })
|
||||
}
|
||||
|
||||
fn analyze_scalar<'a>(&mut self, value: &'a str) -> Result<ScalarAnalysis<'a>, EmitterError> {
|
||||
fn analyze_scalar<'a>(&mut self, value: &'a str) -> Result<ScalarAnalysis<'a>> {
|
||||
let mut block_indicators = false;
|
||||
let mut flow_indicators = false;
|
||||
let mut line_breaks = false;
|
||||
|
@ -1330,7 +1304,7 @@ impl<'w> Emitter<'w> {
|
|||
&mut self,
|
||||
event: &'a Event,
|
||||
tag_directives: &'a [TagDirective],
|
||||
) -> Result<Analysis<'a>, EmitterError> {
|
||||
) -> Result<Analysis<'a>> {
|
||||
let mut analysis = Analysis::default();
|
||||
|
||||
match &event.data {
|
||||
|
@ -1389,13 +1363,13 @@ impl<'w> Emitter<'w> {
|
|||
Ok(analysis)
|
||||
}
|
||||
|
||||
fn write_bom(&mut self) -> Result<(), EmitterError> {
|
||||
fn write_bom(&mut self) -> Result<()> {
|
||||
self.flush_if_needed()?;
|
||||
self.buffer.push('\u{feff}');
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_indent(&mut self) -> Result<(), EmitterError> {
|
||||
fn write_indent(&mut self) -> Result<()> {
|
||||
let indent = if self.indent >= 0 { self.indent } else { 0 };
|
||||
if !self.indention || self.column > indent || self.column == indent && !self.whitespace {
|
||||
self.put_break()?;
|
||||
|
@ -1414,7 +1388,7 @@ impl<'w> Emitter<'w> {
|
|||
need_whitespace: bool,
|
||||
is_whitespace: bool,
|
||||
is_indention: bool,
|
||||
) -> Result<(), EmitterError> {
|
||||
) -> Result<()> {
|
||||
if need_whitespace && !self.whitespace {
|
||||
self.put(' ')?;
|
||||
}
|
||||
|
@ -1424,14 +1398,14 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_anchor(&mut self, value: &str) -> Result<(), EmitterError> {
|
||||
fn write_anchor(&mut self, value: &str) -> Result<()> {
|
||||
self.write_str(value)?;
|
||||
self.whitespace = false;
|
||||
self.indention = false;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_tag_handle(&mut self, value: &str) -> Result<(), EmitterError> {
|
||||
fn write_tag_handle(&mut self, value: &str) -> Result<()> {
|
||||
if !self.whitespace {
|
||||
self.put(' ')?;
|
||||
}
|
||||
|
@ -1441,11 +1415,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_tag_content(
|
||||
&mut self,
|
||||
value: &str,
|
||||
need_whitespace: bool,
|
||||
) -> Result<(), EmitterError> {
|
||||
fn write_tag_content(&mut self, value: &str, need_whitespace: bool) -> Result<()> {
|
||||
if need_whitespace && !self.whitespace {
|
||||
self.put(' ')?;
|
||||
}
|
||||
|
@ -1486,7 +1456,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_plain_scalar(&mut self, value: &str, allow_breaks: bool) -> Result<(), EmitterError> {
|
||||
fn write_plain_scalar(&mut self, value: &str, allow_breaks: bool) -> Result<()> {
|
||||
let mut spaces = false;
|
||||
let mut breaks = false;
|
||||
if !self.whitespace && (!value.is_empty() || self.flow_level != 0) {
|
||||
|
@ -1526,11 +1496,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_single_quoted_scalar(
|
||||
&mut self,
|
||||
value: &str,
|
||||
allow_breaks: bool,
|
||||
) -> Result<(), EmitterError> {
|
||||
fn write_single_quoted_scalar(&mut self, value: &str, allow_breaks: bool) -> Result<()> {
|
||||
let mut spaces = false;
|
||||
let mut breaks = false;
|
||||
self.write_indicator("'", true, false, false)?;
|
||||
|
@ -1584,11 +1550,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_double_quoted_scalar(
|
||||
&mut self,
|
||||
value: &str,
|
||||
allow_breaks: bool,
|
||||
) -> Result<(), EmitterError> {
|
||||
fn write_double_quoted_scalar(&mut self, value: &str, allow_breaks: bool) -> Result<()> {
|
||||
let mut spaces = false;
|
||||
self.write_indicator("\"", true, false, false)?;
|
||||
let mut chars = value.chars();
|
||||
|
@ -1701,7 +1663,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_block_scalar_hints(&mut self, string: &str) -> Result<(), EmitterError> {
|
||||
fn write_block_scalar_hints(&mut self, string: &str) -> Result<()> {
|
||||
let mut chomp_hint: Option<&str> = None;
|
||||
|
||||
let first = string.chars().next();
|
||||
|
@ -1736,7 +1698,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_literal_scalar(&mut self, value: &str) -> Result<(), EmitterError> {
|
||||
fn write_literal_scalar(&mut self, value: &str) -> Result<()> {
|
||||
let mut breaks = true;
|
||||
self.write_indicator("|", true, false, false)?;
|
||||
self.write_block_scalar_hints(value)?;
|
||||
|
@ -1761,7 +1723,7 @@ impl<'w> Emitter<'w> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_folded_scalar(&mut self, value: &str) -> Result<(), EmitterError> {
|
||||
fn write_folded_scalar(&mut self, value: &str) -> Result<()> {
|
||||
let mut breaks = true;
|
||||
let mut leading_spaces = true;
|
||||
self.write_indicator(">", true, false, false)?;
|
||||
|
@ -1806,7 +1768,7 @@ impl<'w> Emitter<'w> {
|
|||
}
|
||||
|
||||
/// Flush the accumulated characters to the output.
|
||||
pub fn flush(&mut self) -> Result<(), WriterError> {
|
||||
pub fn flush(&mut self) -> Result<()> {
|
||||
assert!((self.write_handler).is_some());
|
||||
assert_ne!(self.encoding, Encoding::Any);
|
||||
|
||||
|
|
259
src/error.rs
259
src/error.rs
|
@ -1,5 +1,7 @@
|
|||
pub type Result<T, E = Error> = core::result::Result<T, E>;
|
||||
|
||||
/// The pointer position.
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub struct Mark {
|
||||
/// The position index.
|
||||
|
@ -16,77 +18,230 @@ impl std::fmt::Display for Mark {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum EmitterError {
|
||||
#[error("{0}")]
|
||||
Problem(&'static str),
|
||||
#[error(transparent)]
|
||||
Writer(#[from] WriterError),
|
||||
#[derive(Debug)]
|
||||
#[allow(clippy::struct_field_names)]
|
||||
struct Problem {
|
||||
pub problem: &'static str,
|
||||
pub problem_mark: Mark,
|
||||
pub context: &'static str,
|
||||
pub context_mark: Mark,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum WriterError {
|
||||
#[error(transparent)]
|
||||
Io(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ReaderError {
|
||||
#[error("{problem}")]
|
||||
Problem {
|
||||
#[derive(Debug)]
|
||||
enum ErrorImpl {
|
||||
Reader {
|
||||
problem: &'static str,
|
||||
offset: usize,
|
||||
value: i32,
|
||||
},
|
||||
#[error("input stream produced an invalid byte order marker")]
|
||||
InvalidBom,
|
||||
#[error("invalid UTF-8 byte at offset: {value:x}")]
|
||||
InvalidUtf8 { value: u8 },
|
||||
#[error("invalid UTF-16 unpaired surrogate: {value:x}")]
|
||||
InvalidUtf16 { value: u16 },
|
||||
#[error(transparent)]
|
||||
Io(#[from] std::io::Error),
|
||||
Scanner(Problem),
|
||||
Parser(Problem),
|
||||
Composer(Problem),
|
||||
Emitter(&'static str),
|
||||
Io(std::io::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ScannerError {
|
||||
#[error("{}:{}: {} {} ({}:{})", problem_mark.line, problem_mark.column, problem, context, context_mark.line, context_mark.column)]
|
||||
Problem {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ErrorKind {
|
||||
Reader,
|
||||
Scanner,
|
||||
Parser,
|
||||
Composer,
|
||||
Emitter,
|
||||
Io,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Error(Box<ErrorImpl>);
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(value: std::io::Error) -> Self {
|
||||
Self(Box::new(ErrorImpl::Io(value)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub(crate) fn reader(problem: &'static str, offset: usize, value: i32) -> Self {
|
||||
Self(Box::new(ErrorImpl::Reader {
|
||||
problem,
|
||||
offset,
|
||||
value,
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn scanner(
|
||||
context: &'static str,
|
||||
context_mark: Mark,
|
||||
problem: &'static str,
|
||||
problem_mark: Mark,
|
||||
},
|
||||
#[error(transparent)]
|
||||
Reader(#[from] ReaderError),
|
||||
) -> Self {
|
||||
Self(Box::new(ErrorImpl::Scanner(Problem {
|
||||
problem,
|
||||
problem_mark,
|
||||
context,
|
||||
context_mark,
|
||||
})))
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ParserError {
|
||||
#[error("{}:{}: {}", mark.line, mark.column, problem)]
|
||||
Problem { problem: &'static str, mark: Mark },
|
||||
#[error("{}:{}: {} {} ({}:{})", mark.line, mark.column, problem, context, context_mark.line, context_mark.column)]
|
||||
ProblemWithContext {
|
||||
pub(crate) fn parser(
|
||||
context: &'static str,
|
||||
context_mark: Mark,
|
||||
problem: &'static str,
|
||||
mark: Mark,
|
||||
},
|
||||
#[error(transparent)]
|
||||
Scanner(#[from] ScannerError),
|
||||
problem_mark: Mark,
|
||||
) -> Self {
|
||||
Self(Box::new(ErrorImpl::Parser(Problem {
|
||||
problem,
|
||||
problem_mark,
|
||||
context,
|
||||
context_mark,
|
||||
})))
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ComposerError {
|
||||
#[error("{}:{}: {}", mark.line, mark.column, problem)]
|
||||
Problem { problem: &'static str, mark: Mark },
|
||||
#[error("{}:{}: {} {} ({}:{})", mark.line, mark.column, problem, context, context_mark.line, context_mark.column)]
|
||||
ProblemWithContext {
|
||||
pub(crate) fn composer(
|
||||
context: &'static str,
|
||||
context_mark: Mark,
|
||||
problem: &'static str,
|
||||
mark: Mark,
|
||||
},
|
||||
#[error(transparent)]
|
||||
Parser(#[from] ParserError),
|
||||
problem_mark: Mark,
|
||||
) -> Self {
|
||||
Self(Box::new(ErrorImpl::Composer(Problem {
|
||||
problem,
|
||||
problem_mark,
|
||||
context,
|
||||
context_mark,
|
||||
})))
|
||||
}
|
||||
|
||||
pub(crate) fn emitter(problem: &'static str) -> Self {
|
||||
Self(Box::new(ErrorImpl::Emitter(problem)))
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> ErrorKind {
|
||||
match &*self.0 {
|
||||
ErrorImpl::Reader { .. } => ErrorKind::Reader,
|
||||
ErrorImpl::Scanner(_) => ErrorKind::Scanner,
|
||||
ErrorImpl::Parser(_) => ErrorKind::Parser,
|
||||
ErrorImpl::Composer(_) => ErrorKind::Composer,
|
||||
ErrorImpl::Emitter(_) => ErrorKind::Emitter,
|
||||
ErrorImpl::Io(_) => ErrorKind::Io,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn problem_mark(&self) -> Option<Mark> {
|
||||
match &*self.0 {
|
||||
ErrorImpl::Reader { .. } | ErrorImpl::Emitter(_) | ErrorImpl::Io(_) => None,
|
||||
ErrorImpl::Scanner(ref p) | ErrorImpl::Parser(ref p) | ErrorImpl::Composer(ref p) => {
|
||||
Some(p.problem_mark)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn context_mark(&self) -> Option<Mark> {
|
||||
match &*self.0 {
|
||||
ErrorImpl::Reader { .. } | ErrorImpl::Emitter(..) | ErrorImpl::Io(_) => None,
|
||||
ErrorImpl::Scanner(ref p) | ErrorImpl::Parser(ref p) | ErrorImpl::Composer(ref p) => {
|
||||
if p.context.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(p.context_mark)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn problem(&self) -> &'static str {
|
||||
match &*self.0 {
|
||||
ErrorImpl::Reader { problem, .. } | ErrorImpl::Emitter(problem) => problem,
|
||||
ErrorImpl::Scanner(ref p) | ErrorImpl::Parser(ref p) | ErrorImpl::Composer(ref p) => {
|
||||
p.problem
|
||||
}
|
||||
ErrorImpl::Io(_) => "I/O error",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn context(&self) -> Option<&'static str> {
|
||||
match &*self.0 {
|
||||
ErrorImpl::Reader { .. } | ErrorImpl::Emitter(..) | ErrorImpl::Io(_) => None,
|
||||
ErrorImpl::Scanner(ref p) | ErrorImpl::Parser(ref p) | ErrorImpl::Composer(ref p) => {
|
||||
if p.context.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(p.context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
if let ErrorImpl::Io(ref err) = &*self.0 {
|
||||
Some(err)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Error> for std::io::Error {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: Error) -> Result<Self, Self::Error> {
|
||||
if value.kind() == ErrorKind::Io {
|
||||
if let ErrorImpl::Io(err) = *value.0 {
|
||||
Ok(err)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
} else {
|
||||
Err(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for ErrorKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(match self {
|
||||
ErrorKind::Reader => "Reader",
|
||||
ErrorKind::Scanner => "Scanner",
|
||||
ErrorKind::Parser => "Parser",
|
||||
ErrorKind::Composer => "Composer",
|
||||
ErrorKind::Emitter => "Emitter",
|
||||
ErrorKind::Io => "I/O",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for Problem {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self {
|
||||
problem,
|
||||
problem_mark,
|
||||
context,
|
||||
context_mark,
|
||||
} = self;
|
||||
|
||||
if self.context.is_empty() {
|
||||
write!(f, "{problem_mark}: {problem}")
|
||||
} else {
|
||||
write!(f, "{problem_mark}: {problem} {context} ({context_mark})")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} error: ", self.kind())?;
|
||||
match *self.0 {
|
||||
ErrorImpl::Reader {
|
||||
problem,
|
||||
offset,
|
||||
value,
|
||||
} => write!(f, "{problem} (offset {offset}, value {value})"),
|
||||
ErrorImpl::Scanner(ref p) | ErrorImpl::Parser(ref p) | ErrorImpl::Composer(ref p) => {
|
||||
write!(f, "{p}")
|
||||
}
|
||||
ErrorImpl::Emitter(problem) => write!(f, "{problem}"),
|
||||
ErrorImpl::Io(ref err) => write!(f, "{err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
124
src/parser.rs
124
src/parser.rs
|
@ -3,7 +3,7 @@ use alloc::{vec, vec::Vec};
|
|||
|
||||
use crate::scanner::Scanner;
|
||||
use crate::{
|
||||
Encoding, Event, EventData, MappingStyle, Mark, ParserError, ScalarStyle, SequenceStyle,
|
||||
Encoding, Error, Event, EventData, MappingStyle, Mark, Result, ScalarStyle, SequenceStyle,
|
||||
TagDirective, TokenData, VersionDirective,
|
||||
};
|
||||
|
||||
|
@ -110,7 +110,7 @@ pub struct AliasData {
|
|||
}
|
||||
|
||||
impl<'r> Iterator for Parser<'r> {
|
||||
type Item = Result<Event, ParserError>;
|
||||
type Item = Result<Event>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.scanner.stream_end_produced || self.state == ParserState::End {
|
||||
|
@ -167,35 +167,14 @@ impl<'r> Parser<'r> {
|
|||
/// An application must not alternate the calls of [`Parser::parse()`] with
|
||||
/// the calls of [`Document::load()`](crate::Document::load). Doing this
|
||||
/// will break the parser.
|
||||
pub fn parse(&mut self) -> Result<Event, ParserError> {
|
||||
pub fn parse(&mut self) -> Result<Event> {
|
||||
if self.scanner.stream_end_produced || self.state == ParserState::End {
|
||||
return Ok(Event::stream_end());
|
||||
}
|
||||
self.state_machine()
|
||||
}
|
||||
|
||||
fn set_parser_error<T>(problem: &'static str, problem_mark: Mark) -> Result<T, ParserError> {
|
||||
Err(ParserError::Problem {
|
||||
problem,
|
||||
mark: problem_mark,
|
||||
})
|
||||
}
|
||||
|
||||
fn set_parser_error_context<T>(
|
||||
context: &'static str,
|
||||
context_mark: Mark,
|
||||
problem: &'static str,
|
||||
problem_mark: Mark,
|
||||
) -> Result<T, ParserError> {
|
||||
Err(ParserError::ProblemWithContext {
|
||||
context,
|
||||
context_mark,
|
||||
problem,
|
||||
mark: problem_mark,
|
||||
})
|
||||
}
|
||||
|
||||
fn state_machine(&mut self) -> Result<Event, ParserError> {
|
||||
fn state_machine(&mut self) -> Result<Event> {
|
||||
match self.state {
|
||||
ParserState::StreamStart => self.parse_stream_start(),
|
||||
ParserState::ImplicitDocumentStart => self.parse_document_start(true),
|
||||
|
@ -230,7 +209,7 @@ impl<'r> Parser<'r> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_stream_start(&mut self) -> Result<Event, ParserError> {
|
||||
fn parse_stream_start(&mut self) -> Result<Event> {
|
||||
let token = self.scanner.peek()?;
|
||||
|
||||
if let TokenData::StreamStart { encoding } = &token.data {
|
||||
|
@ -246,11 +225,16 @@ impl<'r> Parser<'r> {
|
|||
Ok(event)
|
||||
} else {
|
||||
let mark = token.start_mark;
|
||||
Self::set_parser_error("did not find expected <stream-start>", mark)
|
||||
Err(Error::parser(
|
||||
"",
|
||||
Mark::default(),
|
||||
"did not find expected <stream-start>",
|
||||
mark,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_document_start(&mut self, implicit: bool) -> Result<Event, ParserError> {
|
||||
fn parse_document_start(&mut self, implicit: bool) -> Result<Event> {
|
||||
let mut version_directive: Option<VersionDirective> = None;
|
||||
|
||||
let mut tag_directives = vec![];
|
||||
|
@ -304,7 +288,12 @@ impl<'r> Parser<'r> {
|
|||
self.scanner.skip_token();
|
||||
Ok(event)
|
||||
} else {
|
||||
Self::set_parser_error("did not find expected <document start>", token.start_mark)
|
||||
Err(Error::parser(
|
||||
"",
|
||||
Mark::default(),
|
||||
"did not find expected <document start>",
|
||||
token.start_mark,
|
||||
))
|
||||
}
|
||||
} else {
|
||||
let event = Event {
|
||||
|
@ -318,7 +307,7 @@ impl<'r> Parser<'r> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_document_content(&mut self) -> Result<Event, ParserError> {
|
||||
fn parse_document_content(&mut self) -> Result<Event> {
|
||||
let token = self.scanner.peek()?;
|
||||
if let TokenData::VersionDirective { .. }
|
||||
| TokenData::TagDirective { .. }
|
||||
|
@ -334,7 +323,7 @@ impl<'r> Parser<'r> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_document_end(&mut self) -> Result<Event, ParserError> {
|
||||
fn parse_document_end(&mut self) -> Result<Event> {
|
||||
let mut end_mark: Mark;
|
||||
let mut implicit = true;
|
||||
let token = self.scanner.peek()?;
|
||||
|
@ -354,7 +343,7 @@ impl<'r> Parser<'r> {
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_node(&mut self, block: bool, indentless_sequence: bool) -> Result<Event, ParserError> {
|
||||
fn parse_node(&mut self, block: bool, indentless_sequence: bool) -> Result<Event> {
|
||||
let mut anchor: Option<String> = None;
|
||||
let mut tag_handle: Option<String> = None;
|
||||
let mut tag_suffix: Option<String> = None;
|
||||
|
@ -424,12 +413,12 @@ impl<'r> Parser<'r> {
|
|||
}
|
||||
}
|
||||
if tag.is_none() {
|
||||
return Self::set_parser_error_context(
|
||||
return Err(Error::parser(
|
||||
"while parsing a node",
|
||||
start_mark,
|
||||
"found undefined tag handle",
|
||||
tag_mark,
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -548,7 +537,7 @@ impl<'r> Parser<'r> {
|
|||
};
|
||||
return Ok(event);
|
||||
} else {
|
||||
return Self::set_parser_error_context(
|
||||
return Err(Error::parser(
|
||||
if block {
|
||||
"while parsing a block node"
|
||||
} else {
|
||||
|
@ -557,11 +546,11 @@ impl<'r> Parser<'r> {
|
|||
start_mark,
|
||||
"did not find expected node content",
|
||||
token.start_mark,
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_block_sequence_entry(&mut self, first: bool) -> Result<Event, ParserError> {
|
||||
fn parse_block_sequence_entry(&mut self, first: bool) -> Result<Event> {
|
||||
if first {
|
||||
let token = self.scanner.peek()?;
|
||||
let mark = token.start_mark;
|
||||
|
@ -595,16 +584,16 @@ impl<'r> Parser<'r> {
|
|||
} else {
|
||||
let token_mark = token.start_mark;
|
||||
let mark = self.marks.pop().unwrap();
|
||||
return Self::set_parser_error_context(
|
||||
return Err(Error::parser(
|
||||
"while parsing a block collection",
|
||||
mark,
|
||||
"did not find expected '-' indicator",
|
||||
token_mark,
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_indentless_sequence_entry(&mut self) -> Result<Event, ParserError> {
|
||||
fn parse_indentless_sequence_entry(&mut self) -> Result<Event> {
|
||||
let mut token = self.scanner.peek()?;
|
||||
if let TokenData::BlockEntry = token.data {
|
||||
let mark: Mark = token.end_mark;
|
||||
|
@ -632,7 +621,7 @@ impl<'r> Parser<'r> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_block_mapping_key(&mut self, first: bool) -> Result<Event, ParserError> {
|
||||
fn parse_block_mapping_key(&mut self, first: bool) -> Result<Event> {
|
||||
if first {
|
||||
let token = self.scanner.peek()?;
|
||||
let mark = token.start_mark;
|
||||
|
@ -668,16 +657,16 @@ impl<'r> Parser<'r> {
|
|||
} else {
|
||||
let token_mark = token.start_mark;
|
||||
let mark = self.marks.pop().unwrap();
|
||||
Self::set_parser_error_context(
|
||||
Err(Error::parser(
|
||||
"while parsing a block mapping",
|
||||
mark,
|
||||
"did not find expected key",
|
||||
token_mark,
|
||||
)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_block_mapping_value(&mut self) -> Result<Event, ParserError> {
|
||||
fn parse_block_mapping_value(&mut self) -> Result<Event> {
|
||||
let mut token = self.scanner.peek()?;
|
||||
if let TokenData::Value = token.data {
|
||||
let mark: Mark = token.end_mark;
|
||||
|
@ -700,7 +689,7 @@ impl<'r> Parser<'r> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_flow_sequence_entry(&mut self, first: bool) -> Result<Event, ParserError> {
|
||||
fn parse_flow_sequence_entry(&mut self, first: bool) -> Result<Event> {
|
||||
if first {
|
||||
let token = self.scanner.peek()?;
|
||||
let mark = token.start_mark;
|
||||
|
@ -717,12 +706,12 @@ impl<'r> Parser<'r> {
|
|||
} else {
|
||||
let token_mark = token.start_mark;
|
||||
let mark = self.marks.pop().unwrap();
|
||||
return Self::set_parser_error_context(
|
||||
return Err(Error::parser(
|
||||
"while parsing a flow sequence",
|
||||
mark,
|
||||
"did not find expected ',' or ']'",
|
||||
token_mark,
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
if let TokenData::Key = token.data {
|
||||
|
@ -755,7 +744,7 @@ impl<'r> Parser<'r> {
|
|||
Ok(event)
|
||||
}
|
||||
|
||||
fn parse_flow_sequence_entry_mapping_key(&mut self) -> Result<Event, ParserError> {
|
||||
fn parse_flow_sequence_entry_mapping_key(&mut self) -> Result<Event> {
|
||||
let token = self.scanner.peek()?;
|
||||
if matches!(
|
||||
token.data,
|
||||
|
@ -771,7 +760,7 @@ impl<'r> Parser<'r> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_flow_sequence_entry_mapping_value(&mut self) -> Result<Event, ParserError> {
|
||||
fn parse_flow_sequence_entry_mapping_value(&mut self) -> Result<Event> {
|
||||
let mut token = self.scanner.peek()?;
|
||||
if let TokenData::Value = token.data {
|
||||
self.scanner.skip_token();
|
||||
|
@ -789,7 +778,7 @@ impl<'r> Parser<'r> {
|
|||
Self::process_empty_scalar(mark)
|
||||
}
|
||||
|
||||
fn parse_flow_sequence_entry_mapping_end(&mut self) -> Result<Event, ParserError> {
|
||||
fn parse_flow_sequence_entry_mapping_end(&mut self) -> Result<Event> {
|
||||
let token = self.scanner.peek()?;
|
||||
let start_mark = token.start_mark;
|
||||
let end_mark = token.end_mark;
|
||||
|
@ -801,7 +790,7 @@ impl<'r> Parser<'r> {
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_flow_mapping_key(&mut self, first: bool) -> Result<Event, ParserError> {
|
||||
fn parse_flow_mapping_key(&mut self, first: bool) -> Result<Event> {
|
||||
if first {
|
||||
let token = self.scanner.peek()?;
|
||||
let mark = token.start_mark;
|
||||
|
@ -818,12 +807,12 @@ impl<'r> Parser<'r> {
|
|||
} else {
|
||||
let token_mark = token.start_mark;
|
||||
let mark = self.marks.pop().unwrap();
|
||||
return Self::set_parser_error_context(
|
||||
return Err(Error::parser(
|
||||
"while parsing a flow mapping",
|
||||
mark,
|
||||
"did not find expected ',' or '}'",
|
||||
token_mark,
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
if let TokenData::Key = token.data {
|
||||
|
@ -855,7 +844,7 @@ impl<'r> Parser<'r> {
|
|||
Ok(event)
|
||||
}
|
||||
|
||||
fn parse_flow_mapping_value(&mut self, empty: bool) -> Result<Event, ParserError> {
|
||||
fn parse_flow_mapping_value(&mut self, empty: bool) -> Result<Event> {
|
||||
let mut token = self.scanner.peek()?;
|
||||
if empty {
|
||||
let mark = token.start_mark;
|
||||
|
@ -875,7 +864,7 @@ impl<'r> Parser<'r> {
|
|||
Self::process_empty_scalar(mark)
|
||||
}
|
||||
|
||||
fn process_empty_scalar(mark: Mark) -> Result<Event, ParserError> {
|
||||
fn process_empty_scalar(mark: Mark) -> Result<Event> {
|
||||
Ok(Event {
|
||||
data: EventData::Scalar {
|
||||
anchor: None,
|
||||
|
@ -894,7 +883,7 @@ impl<'r> Parser<'r> {
|
|||
&mut self,
|
||||
version_directive_ref: Option<&mut Option<VersionDirective>>,
|
||||
tag_directives_ref: Option<&mut Vec<TagDirective>>,
|
||||
) -> Result<(), ParserError> {
|
||||
) -> Result<()> {
|
||||
let default_tag_directives: [TagDirective; 2] = [
|
||||
// TODO: Get rid of these heap allocations.
|
||||
TagDirective {
|
||||
|
@ -923,9 +912,19 @@ impl<'r> Parser<'r> {
|
|||
if let TokenData::VersionDirective { major, minor } = &token.data {
|
||||
let mark = token.start_mark;
|
||||
if version_directive.is_some() {
|
||||
return Self::set_parser_error("found duplicate %YAML directive", mark);
|
||||
return Err(Error::parser(
|
||||
"",
|
||||
Mark::default(),
|
||||
"found duplicate %YAML directive",
|
||||
mark,
|
||||
));
|
||||
} else if *major != 1 || *minor != 1 && *minor != 2 {
|
||||
return Self::set_parser_error("found incompatible YAML document", mark);
|
||||
return Err(Error::parser(
|
||||
"",
|
||||
Mark::default(),
|
||||
"found incompatible YAML document",
|
||||
mark,
|
||||
));
|
||||
}
|
||||
version_directive = Some(VersionDirective {
|
||||
major: *major,
|
||||
|
@ -973,13 +972,18 @@ impl<'r> Parser<'r> {
|
|||
value: TagDirective,
|
||||
allow_duplicates: bool,
|
||||
mark: Mark,
|
||||
) -> Result<(), ParserError> {
|
||||
) -> Result<()> {
|
||||
for tag_directive in &self.tag_directives {
|
||||
if value.handle == tag_directive.handle {
|
||||
if allow_duplicates {
|
||||
return Ok(());
|
||||
}
|
||||
return Self::set_parser_error("found duplicate %TAG directive", mark);
|
||||
return Err(Error::parser(
|
||||
"",
|
||||
Mark::default(),
|
||||
"found duplicate %TAG directive",
|
||||
mark,
|
||||
));
|
||||
}
|
||||
}
|
||||
self.tag_directives.push(value);
|
||||
|
|
|
@ -2,27 +2,13 @@ use std::io::BufRead;
|
|||
|
||||
use alloc::collections::VecDeque;
|
||||
|
||||
use crate::{scanner::Scanner, Encoding, ReaderError};
|
||||
|
||||
fn yaml_parser_set_reader_error<T>(
|
||||
problem: &'static str,
|
||||
offset: usize,
|
||||
value: i32,
|
||||
) -> Result<T, ReaderError> {
|
||||
Err(ReaderError::Problem {
|
||||
problem,
|
||||
offset,
|
||||
value,
|
||||
})
|
||||
}
|
||||
use crate::{scanner::Scanner, Encoding, Error, Result};
|
||||
|
||||
const BOM_UTF8: [u8; 3] = [0xef, 0xbb, 0xbf];
|
||||
const BOM_UTF16LE: [u8; 2] = [0xff, 0xfe];
|
||||
const BOM_UTF16BE: [u8; 2] = [0xfe, 0xff];
|
||||
|
||||
fn yaml_parser_determine_encoding(
|
||||
reader: &mut dyn BufRead,
|
||||
) -> Result<Option<Encoding>, ReaderError> {
|
||||
fn yaml_parser_determine_encoding(reader: &mut dyn BufRead) -> Result<Option<Encoding>> {
|
||||
let initial_bytes = reader.fill_buf()?;
|
||||
if initial_bytes.is_empty() {
|
||||
return Ok(None);
|
||||
|
@ -35,7 +21,11 @@ fn yaml_parser_determine_encoding(
|
|||
if bom == BOM_UTF8 {
|
||||
Ok(Some(Encoding::Utf8))
|
||||
} else {
|
||||
Err(ReaderError::InvalidBom)
|
||||
Err(Error::reader(
|
||||
"invalid byte order marker",
|
||||
0,
|
||||
i32::from_be_bytes([bom[0], bom[1], bom[2], 0]),
|
||||
))
|
||||
}
|
||||
}
|
||||
0xff | 0xfe => {
|
||||
|
@ -46,7 +36,11 @@ fn yaml_parser_determine_encoding(
|
|||
} else if bom == BOM_UTF16BE {
|
||||
Ok(Some(Encoding::Utf16Be))
|
||||
} else {
|
||||
Err(ReaderError::InvalidBom)
|
||||
Err(Error::reader(
|
||||
"invalid byte order marker",
|
||||
0,
|
||||
i32::from_le_bytes([bom[0], bom[1], 0, 0]),
|
||||
))
|
||||
}
|
||||
}
|
||||
_ => Ok(Some(Encoding::Utf8)),
|
||||
|
@ -60,7 +54,7 @@ fn read_utf8_buffered(
|
|||
reader: &mut dyn BufRead,
|
||||
out: &mut VecDeque<char>,
|
||||
offset: &mut usize,
|
||||
) -> Result<bool, ReaderError> {
|
||||
) -> Result<bool> {
|
||||
let available = loop {
|
||||
match reader.fill_buf() {
|
||||
Ok([]) => return Ok(false),
|
||||
|
@ -96,9 +90,11 @@ fn read_utf8_buffered(
|
|||
}
|
||||
|
||||
match err.error_len() {
|
||||
Some(_invalid_len) => Err(ReaderError::InvalidUtf8 {
|
||||
value: available[valid_bytes],
|
||||
}),
|
||||
Some(_invalid_len) => Err(Error::reader(
|
||||
"invalid UTF-8",
|
||||
*offset,
|
||||
available[valid_bytes] as _,
|
||||
)),
|
||||
None => {
|
||||
if valid_bytes != 0 {
|
||||
// Some valid UTF-8 characters were present, and the
|
||||
|
@ -128,7 +124,7 @@ fn read_utf8_char_unbuffered(
|
|||
out: &mut VecDeque<char>,
|
||||
initial: u8,
|
||||
offset: &mut usize,
|
||||
) -> Result<(), ReaderError> {
|
||||
) -> Result<()> {
|
||||
let width = utf8_char_width(initial);
|
||||
let mut buffer = [0; 4];
|
||||
reader.read_exact(&mut buffer[..width])?;
|
||||
|
@ -143,7 +139,7 @@ fn read_utf8_char_unbuffered(
|
|||
} else {
|
||||
// Since we read the exact character width, the only
|
||||
// possible error here is invalid Unicode.
|
||||
Err(ReaderError::InvalidUtf8 { value: buffer[0] })
|
||||
Err(Error::reader("invalid UTF-8", *offset, buffer[0] as _))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +147,7 @@ fn read_utf16_buffered<const BIG_ENDIAN: bool>(
|
|||
reader: &mut dyn BufRead,
|
||||
out: &mut VecDeque<char>,
|
||||
offset: &mut usize,
|
||||
) -> Result<bool, ReaderError> {
|
||||
) -> Result<bool> {
|
||||
let available = loop {
|
||||
match reader.fill_buf() {
|
||||
Ok([]) => return Ok(false),
|
||||
|
@ -206,7 +202,7 @@ fn read_utf16_char_unbuffered<const BIG_ENDIAN: bool>(
|
|||
reader: &mut dyn BufRead,
|
||||
out: &mut VecDeque<char>,
|
||||
offset: &mut usize,
|
||||
) -> Result<(), ReaderError> {
|
||||
) -> Result<()> {
|
||||
let mut buffer = [0; 2];
|
||||
reader.read_exact(&mut buffer)?;
|
||||
let first = if BIG_ENDIAN {
|
||||
|
@ -229,9 +225,11 @@ fn read_utf16_char_unbuffered<const BIG_ENDIAN: bool>(
|
|||
*offset += 4;
|
||||
Ok(())
|
||||
}
|
||||
Some(Err(err)) => Err(ReaderError::InvalidUtf16 {
|
||||
value: err.unpaired_surrogate(),
|
||||
}),
|
||||
Some(Err(err)) => Err(Error::reader(
|
||||
"invalid UTF-16",
|
||||
*offset,
|
||||
err.unpaired_surrogate() as _,
|
||||
)),
|
||||
None => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
|
@ -264,7 +262,7 @@ fn is_utf16_surrogate(value: u16) -> bool {
|
|||
matches!(value, 0xD800..=0xDFFF)
|
||||
}
|
||||
|
||||
fn push_char(out: &mut VecDeque<char>, ch: char, offset: usize) -> Result<(), ReaderError> {
|
||||
fn push_char(out: &mut VecDeque<char>, ch: char, offset: usize) -> Result<()> {
|
||||
if !(ch == '\x09'
|
||||
|| ch == '\x0A'
|
||||
|| ch == '\x0D'
|
||||
|
@ -274,16 +272,17 @@ fn push_char(out: &mut VecDeque<char>, ch: char, offset: usize) -> Result<(), Re
|
|||
|| ch >= '\u{E000}' && ch <= '\u{FFFD}'
|
||||
|| ch >= '\u{10000}' && ch <= '\u{10FFFF}')
|
||||
{
|
||||
return yaml_parser_set_reader_error("control characters are not allowed", offset, ch as _);
|
||||
return Err(Error::reader(
|
||||
"control characters are not allowed",
|
||||
offset,
|
||||
ch as _,
|
||||
));
|
||||
}
|
||||
out.push_back(ch);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn yaml_parser_update_buffer(
|
||||
parser: &mut Scanner,
|
||||
length: usize,
|
||||
) -> Result<(), ReaderError> {
|
||||
pub(crate) fn yaml_parser_update_buffer(parser: &mut Scanner, length: usize) -> Result<()> {
|
||||
let reader = parser.read_handler.as_deref_mut().expect("no read handler");
|
||||
if parser.buffer.len() >= length {
|
||||
return Ok(());
|
||||
|
@ -319,7 +318,7 @@ pub(crate) fn yaml_parser_update_buffer(
|
|||
}
|
||||
|
||||
if parser.offset >= (!0_usize).wrapping_div(2_usize) {
|
||||
return yaml_parser_set_reader_error("input is too long", parser.offset, -1);
|
||||
return Err(Error::reader("input is too long", parser.offset, -1));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
111
src/scanner.rs
111
src/scanner.rs
|
@ -5,8 +5,7 @@ use alloc::string::String;
|
|||
use crate::macros::{is_blankz, is_break};
|
||||
use crate::reader::yaml_parser_update_buffer;
|
||||
use crate::{
|
||||
Encoding, Mark, ReaderError, ScalarStyle, ScannerError, SimpleKey, Token, TokenData,
|
||||
INPUT_BUFFER_SIZE,
|
||||
Encoding, Error, Mark, Result, ScalarStyle, SimpleKey, Token, TokenData, INPUT_BUFFER_SIZE,
|
||||
};
|
||||
|
||||
const MAX_NUMBER_LENGTH: u64 = 9_u64;
|
||||
|
@ -92,7 +91,7 @@ impl<'r> Scanner<'r> {
|
|||
self.encoding = encoding;
|
||||
}
|
||||
|
||||
fn cache(&mut self, length: usize) -> Result<(), ReaderError> {
|
||||
fn cache(&mut self, length: usize) -> Result<()> {
|
||||
if self.buffer.len() >= length {
|
||||
Ok(())
|
||||
} else {
|
||||
|
@ -170,7 +169,7 @@ impl<'r> Scanner<'r> {
|
|||
/// corresponding to the input stream. The initial token has the type
|
||||
/// [`TokenData::StreamStart`] while the ending token has the type
|
||||
/// [`TokenData::StreamEnd`].
|
||||
pub fn scan(&mut self) -> Result<Token, ScannerError> {
|
||||
pub fn scan(&mut self) -> Result<Token> {
|
||||
if self.stream_end_produced {
|
||||
return Ok(Token {
|
||||
data: TokenData::StreamEnd,
|
||||
|
@ -194,7 +193,7 @@ impl<'r> Scanner<'r> {
|
|||
}
|
||||
|
||||
/// Equivalent of the libyaml `PEEK_TOKEN` macro, used by the parser.
|
||||
pub(crate) fn peek(&mut self) -> Result<&Token, ScannerError> {
|
||||
pub(crate) fn peek(&mut self) -> Result<&Token> {
|
||||
if self.token_available {
|
||||
return Ok(self
|
||||
.tokens
|
||||
|
@ -213,7 +212,7 @@ impl<'r> Scanner<'r> {
|
|||
}
|
||||
|
||||
/// Equivalent of the libyaml `PEEK_TOKEN` macro, used by the parser.
|
||||
pub(crate) fn peek_mut(&mut self) -> Result<&mut Token, ScannerError> {
|
||||
pub(crate) fn peek_mut(&mut self) -> Result<&mut Token> {
|
||||
if self.token_available {
|
||||
return Ok(self
|
||||
.tokens
|
||||
|
@ -250,16 +249,11 @@ impl<'r> Scanner<'r> {
|
|||
context: &'static str,
|
||||
context_mark: Mark,
|
||||
problem: &'static str,
|
||||
) -> Result<T, ScannerError> {
|
||||
Err(ScannerError::Problem {
|
||||
context,
|
||||
context_mark,
|
||||
problem,
|
||||
problem_mark: self.mark,
|
||||
})
|
||||
) -> Result<T> {
|
||||
Err(Error::scanner(context, context_mark, problem, self.mark))
|
||||
}
|
||||
|
||||
pub(crate) fn fetch_more_tokens(&mut self) -> Result<(), ScannerError> {
|
||||
pub(crate) fn fetch_more_tokens(&mut self) -> Result<()> {
|
||||
let mut need_more_tokens;
|
||||
loop {
|
||||
need_more_tokens = false;
|
||||
|
@ -283,7 +277,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_next_token(&mut self) -> Result<(), ScannerError> {
|
||||
fn fetch_next_token(&mut self) -> Result<()> {
|
||||
self.cache(1)?;
|
||||
if !self.stream_start_produced {
|
||||
self.fetch_stream_start();
|
||||
|
@ -394,7 +388,7 @@ impl<'r> Scanner<'r> {
|
|||
)
|
||||
}
|
||||
|
||||
fn stale_simple_keys(&mut self) -> Result<(), ScannerError> {
|
||||
fn stale_simple_keys(&mut self) -> Result<()> {
|
||||
for simple_key in &mut self.simple_keys {
|
||||
let mark = simple_key.mark;
|
||||
if simple_key.possible
|
||||
|
@ -414,7 +408,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn save_simple_key(&mut self) -> Result<(), ScannerError> {
|
||||
fn save_simple_key(&mut self) -> Result<()> {
|
||||
let required = self.flow_level == 0 && self.indent as u64 == self.mark.column;
|
||||
if self.simple_key_allowed {
|
||||
let simple_key = SimpleKey {
|
||||
|
@ -429,7 +423,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_simple_key(&mut self) -> Result<(), ScannerError> {
|
||||
fn remove_simple_key(&mut self) -> Result<()> {
|
||||
let simple_key: &mut SimpleKey = self.simple_keys.last_mut().unwrap();
|
||||
if simple_key.possible {
|
||||
let mark = simple_key.mark;
|
||||
|
@ -445,7 +439,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn increase_flow_level(&mut self) -> Result<(), ScannerError> {
|
||||
fn increase_flow_level(&mut self) -> Result<()> {
|
||||
let empty_simple_key = SimpleKey {
|
||||
possible: false,
|
||||
required: false,
|
||||
|
@ -472,13 +466,7 @@ impl<'r> Scanner<'r> {
|
|||
}
|
||||
}
|
||||
|
||||
fn roll_indent(
|
||||
&mut self,
|
||||
column: i64,
|
||||
number: i64,
|
||||
data: TokenData,
|
||||
mark: Mark,
|
||||
) -> Result<(), ScannerError> {
|
||||
fn roll_indent(&mut self, column: i64, number: i64, data: TokenData, mark: Mark) -> Result<()> {
|
||||
if self.flow_level != 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -541,7 +529,7 @@ impl<'r> Scanner<'r> {
|
|||
self.tokens.push_back(token);
|
||||
}
|
||||
|
||||
fn fetch_stream_end(&mut self) -> Result<(), ScannerError> {
|
||||
fn fetch_stream_end(&mut self) -> Result<()> {
|
||||
if self.mark.column != 0_u64 {
|
||||
self.mark.column = 0_u64;
|
||||
self.mark.line += 1;
|
||||
|
@ -558,7 +546,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_directive(&mut self) -> Result<(), ScannerError> {
|
||||
fn fetch_directive(&mut self) -> Result<()> {
|
||||
self.unroll_indent(-1_i64);
|
||||
self.remove_simple_key()?;
|
||||
self.simple_key_allowed = false;
|
||||
|
@ -567,7 +555,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_document_indicator(&mut self, data: TokenData) -> Result<(), ScannerError> {
|
||||
fn fetch_document_indicator(&mut self, data: TokenData) -> Result<()> {
|
||||
self.unroll_indent(-1_i64);
|
||||
self.remove_simple_key()?;
|
||||
self.simple_key_allowed = false;
|
||||
|
@ -586,7 +574,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_flow_collection_start(&mut self, data: TokenData) -> Result<(), ScannerError> {
|
||||
fn fetch_flow_collection_start(&mut self, data: TokenData) -> Result<()> {
|
||||
self.save_simple_key()?;
|
||||
self.increase_flow_level()?;
|
||||
self.simple_key_allowed = true;
|
||||
|
@ -602,7 +590,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_flow_collection_end(&mut self, data: TokenData) -> Result<(), ScannerError> {
|
||||
fn fetch_flow_collection_end(&mut self, data: TokenData) -> Result<()> {
|
||||
self.remove_simple_key()?;
|
||||
self.decrease_flow_level();
|
||||
self.simple_key_allowed = false;
|
||||
|
@ -618,7 +606,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_flow_entry(&mut self) -> Result<(), ScannerError> {
|
||||
fn fetch_flow_entry(&mut self) -> Result<()> {
|
||||
self.remove_simple_key()?;
|
||||
self.simple_key_allowed = true;
|
||||
let start_mark: Mark = self.mark;
|
||||
|
@ -633,7 +621,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_block_entry(&mut self) -> Result<(), ScannerError> {
|
||||
fn fetch_block_entry(&mut self) -> Result<()> {
|
||||
if self.flow_level == 0 {
|
||||
if !self.simple_key_allowed {
|
||||
return self.set_scanner_error(
|
||||
|
@ -663,7 +651,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_key(&mut self) -> Result<(), ScannerError> {
|
||||
fn fetch_key(&mut self) -> Result<()> {
|
||||
if self.flow_level == 0 {
|
||||
if !self.simple_key_allowed {
|
||||
return self.set_scanner_error(
|
||||
|
@ -693,7 +681,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_value(&mut self) -> Result<(), ScannerError> {
|
||||
fn fetch_value(&mut self) -> Result<()> {
|
||||
let simple_key: &mut SimpleKey = self.simple_keys.last_mut().unwrap();
|
||||
if simple_key.possible {
|
||||
let token = Token {
|
||||
|
@ -746,7 +734,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_anchor(&mut self, fetch_alias_instead_of_anchor: bool) -> Result<(), ScannerError> {
|
||||
fn fetch_anchor(&mut self, fetch_alias_instead_of_anchor: bool) -> Result<()> {
|
||||
self.save_simple_key()?;
|
||||
self.simple_key_allowed = false;
|
||||
let token = self.scan_anchor(fetch_alias_instead_of_anchor)?;
|
||||
|
@ -754,7 +742,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_tag(&mut self) -> Result<(), ScannerError> {
|
||||
fn fetch_tag(&mut self) -> Result<()> {
|
||||
self.save_simple_key()?;
|
||||
self.simple_key_allowed = false;
|
||||
let token = self.scan_tag()?;
|
||||
|
@ -762,7 +750,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_block_scalar(&mut self, literal: bool) -> Result<(), ScannerError> {
|
||||
fn fetch_block_scalar(&mut self, literal: bool) -> Result<()> {
|
||||
self.remove_simple_key()?;
|
||||
self.simple_key_allowed = true;
|
||||
let token = self.scan_block_scalar(literal)?;
|
||||
|
@ -770,7 +758,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_flow_scalar(&mut self, single: bool) -> Result<(), ScannerError> {
|
||||
fn fetch_flow_scalar(&mut self, single: bool) -> Result<()> {
|
||||
self.save_simple_key()?;
|
||||
self.simple_key_allowed = false;
|
||||
let token = self.scan_flow_scalar(single)?;
|
||||
|
@ -778,7 +766,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_plain_scalar(&mut self) -> Result<(), ScannerError> {
|
||||
fn fetch_plain_scalar(&mut self) -> Result<()> {
|
||||
self.save_simple_key()?;
|
||||
self.simple_key_allowed = false;
|
||||
let token = self.scan_plain_scalar()?;
|
||||
|
@ -786,7 +774,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn scan_to_next_token(&mut self) -> Result<(), ScannerError> {
|
||||
fn scan_to_next_token(&mut self) -> Result<()> {
|
||||
loop {
|
||||
self.cache(1)?;
|
||||
if self.mark.column == 0 && IS_BOM!(self.buffer) {
|
||||
|
@ -817,7 +805,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn scan_directive(&mut self) -> Result<Token, ScannerError> {
|
||||
fn scan_directive(&mut self) -> Result<Token> {
|
||||
let end_mark: Mark;
|
||||
let mut major: i32 = 0;
|
||||
let mut minor: i32 = 0;
|
||||
|
@ -882,7 +870,7 @@ impl<'r> Scanner<'r> {
|
|||
}
|
||||
}
|
||||
|
||||
fn scan_directive_name(&mut self, start_mark: Mark) -> Result<String, ScannerError> {
|
||||
fn scan_directive_name(&mut self, start_mark: Mark) -> Result<String> {
|
||||
let mut string = String::new();
|
||||
self.cache(1)?;
|
||||
|
||||
|
@ -916,7 +904,7 @@ impl<'r> Scanner<'r> {
|
|||
start_mark: Mark,
|
||||
major: &mut i32,
|
||||
minor: &mut i32,
|
||||
) -> Result<(), ScannerError> {
|
||||
) -> Result<()> {
|
||||
self.cache(1)?;
|
||||
while IS_BLANK!(self.buffer) {
|
||||
self.skip_char();
|
||||
|
@ -934,11 +922,7 @@ impl<'r> Scanner<'r> {
|
|||
self.scan_version_directive_number(start_mark, minor)
|
||||
}
|
||||
|
||||
fn scan_version_directive_number(
|
||||
&mut self,
|
||||
start_mark: Mark,
|
||||
number: &mut i32,
|
||||
) -> Result<(), ScannerError> {
|
||||
fn scan_version_directive_number(&mut self, start_mark: Mark, number: &mut i32) -> Result<()> {
|
||||
let mut value: i32 = 0;
|
||||
let mut length = 0;
|
||||
self.cache(1)?;
|
||||
|
@ -967,10 +951,7 @@ impl<'r> Scanner<'r> {
|
|||
}
|
||||
|
||||
// Returns (handle, prefix)
|
||||
fn scan_tag_directive_value(
|
||||
&mut self,
|
||||
start_mark: Mark,
|
||||
) -> Result<(String, String), ScannerError> {
|
||||
fn scan_tag_directive_value(&mut self, start_mark: Mark) -> Result<(String, String)> {
|
||||
self.cache(1)?;
|
||||
|
||||
loop {
|
||||
|
@ -1010,7 +991,7 @@ impl<'r> Scanner<'r> {
|
|||
}
|
||||
}
|
||||
|
||||
fn scan_anchor(&mut self, scan_alias_instead_of_anchor: bool) -> Result<Token, ScannerError> {
|
||||
fn scan_anchor(&mut self, scan_alias_instead_of_anchor: bool) -> Result<Token> {
|
||||
let mut length: i32 = 0;
|
||||
|
||||
let mut string = String::new();
|
||||
|
@ -1060,7 +1041,7 @@ impl<'r> Scanner<'r> {
|
|||
}
|
||||
}
|
||||
|
||||
fn scan_tag(&mut self) -> Result<Token, ScannerError> {
|
||||
fn scan_tag(&mut self) -> Result<Token> {
|
||||
let mut handle;
|
||||
let mut suffix;
|
||||
|
||||
|
@ -1115,11 +1096,7 @@ impl<'r> Scanner<'r> {
|
|||
})
|
||||
}
|
||||
|
||||
fn scan_tag_handle(
|
||||
&mut self,
|
||||
directive: bool,
|
||||
start_mark: Mark,
|
||||
) -> Result<String, ScannerError> {
|
||||
fn scan_tag_handle(&mut self, directive: bool, start_mark: Mark) -> Result<String> {
|
||||
let mut string = String::new();
|
||||
self.cache(1)?;
|
||||
|
||||
|
@ -1162,7 +1139,7 @@ impl<'r> Scanner<'r> {
|
|||
directive: bool,
|
||||
head: Option<&str>,
|
||||
start_mark: Mark,
|
||||
) -> Result<String, ScannerError> {
|
||||
) -> Result<String> {
|
||||
let head = head.unwrap_or("");
|
||||
let mut length = head.len();
|
||||
let mut string = String::new();
|
||||
|
@ -1223,7 +1200,7 @@ impl<'r> Scanner<'r> {
|
|||
directive: bool,
|
||||
start_mark: Mark,
|
||||
string: &mut String,
|
||||
) -> Result<(), ScannerError> {
|
||||
) -> Result<()> {
|
||||
let mut width: i32 = 0;
|
||||
loop {
|
||||
self.cache(3)?;
|
||||
|
@ -1289,7 +1266,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn scan_block_scalar(&mut self, literal: bool) -> Result<Token, ScannerError> {
|
||||
fn scan_block_scalar(&mut self, literal: bool) -> Result<Token> {
|
||||
let mut end_mark: Mark;
|
||||
let mut string = String::new();
|
||||
let mut leading_break = String::new();
|
||||
|
@ -1447,7 +1424,7 @@ impl<'r> Scanner<'r> {
|
|||
breaks: &mut String,
|
||||
start_mark: Mark,
|
||||
end_mark: &mut Mark,
|
||||
) -> Result<(), ScannerError> {
|
||||
) -> Result<()> {
|
||||
let mut max_indent: i32 = 0;
|
||||
*end_mark = self.mark;
|
||||
loop {
|
||||
|
@ -1485,7 +1462,7 @@ impl<'r> Scanner<'r> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn scan_flow_scalar(&mut self, single: bool) -> Result<Token, ScannerError> {
|
||||
fn scan_flow_scalar(&mut self, single: bool) -> Result<Token> {
|
||||
let mut string = String::new();
|
||||
let mut leading_break = String::new();
|
||||
let mut trailing_breaks = String::new();
|
||||
|
@ -1718,7 +1695,7 @@ impl<'r> Scanner<'r> {
|
|||
})
|
||||
}
|
||||
|
||||
fn scan_plain_scalar(&mut self) -> Result<Token, ScannerError> {
|
||||
fn scan_plain_scalar(&mut self) -> Result<Token> {
|
||||
let mut end_mark: Mark;
|
||||
let mut string = String::new();
|
||||
let mut leading_break = String::new();
|
||||
|
@ -1856,7 +1833,7 @@ impl<'r> Default for Scanner<'r> {
|
|||
}
|
||||
|
||||
impl<'r> Iterator for Scanner<'r> {
|
||||
type Item = Result<Token, ScannerError>;
|
||||
type Item = Result<Token>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.stream_end_produced {
|
||||
|
|
Loading…
Reference in a new issue