Box errors, remove thiserror

This commit is contained in:
Simon Ask Ulsnes 2024-02-08 10:49:36 +01:00
parent 8f6ce4bf4a
commit 4f9ef3221e
8 changed files with 456 additions and 399 deletions

View file

@ -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"]

View file

@ -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

View file

@ -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 {

View file

@ -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);

View file

@ -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}"),
}
}
}

View file

@ -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);

View file

@ -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(())
}

View file

@ -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 {