Emitter: Rustify errors

This commit is contained in:
Simon Ask Ulsnes 2024-01-31 22:32:43 +01:00
parent 28f28b472b
commit d1357d92df
7 changed files with 131 additions and 161 deletions

View file

@ -2,7 +2,7 @@ use alloc::string::String;
use alloc::vec::Vec;
use crate::externs::memcpy;
use crate::yaml::{size_t, Write, YamlEventData, YamlNodeData};
use crate::yaml::{size_t, YamlEventData, YamlNodeData};
use crate::{
libc, yaml_break_t, yaml_document_t, yaml_emitter_t, yaml_encoding_t, yaml_event_t,
yaml_mapping_style_t, yaml_mark_t, yaml_node_pair_t, yaml_node_t, yaml_parser_t,
@ -146,7 +146,7 @@ pub fn yaml_emitter_delete(emitter: &mut yaml_emitter_t) {
/// YAML_WRITE_ERROR error.
pub unsafe fn yaml_emitter_set_output_string<'w>(
emitter: &mut yaml_emitter_t<'w>,
output: &'w mut String,
output: &'w mut Vec<u8>,
) {
__assert!(emitter.write_handler.is_none());
if emitter.encoding == YAML_ANY_ENCODING {
@ -161,7 +161,7 @@ pub unsafe fn yaml_emitter_set_output_string<'w>(
/// Set a generic output handler.
pub unsafe fn yaml_emitter_set_output<'w>(
emitter: &mut yaml_emitter_t<'w>,
handler: &'w mut dyn Write,
handler: &'w mut dyn std::io::Write,
) {
__assert!(emitter.write_handler.is_none());
emitter.write_handler = Some(handler);

View file

@ -23,9 +23,8 @@ use libyaml_safer::{
yaml_sequence_end_event_initialize, yaml_sequence_start_event_initialize,
yaml_stream_end_event_initialize, yaml_stream_start_event_initialize, YAML_ANY_SCALAR_STYLE,
YAML_BLOCK_MAPPING_STYLE, YAML_BLOCK_SEQUENCE_STYLE, YAML_DOUBLE_QUOTED_SCALAR_STYLE,
YAML_EMITTER_ERROR, YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE, YAML_MEMORY_ERROR,
YAML_PLAIN_SCALAR_STYLE, YAML_SINGLE_QUOTED_SCALAR_STYLE, YAML_UTF8_ENCODING,
YAML_WRITER_ERROR,
YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE, YAML_PLAIN_SCALAR_STYLE,
YAML_SINGLE_QUOTED_SCALAR_STYLE, YAML_UTF8_ENCODING,
};
use std::env;
use std::error::Error;
@ -34,16 +33,6 @@ use std::io::{self, BufRead, Read, Write};
use std::mem::MaybeUninit;
use std::process::ExitCode;
struct WrapWrite<'w>(&'w mut dyn Write);
impl<'w> libyaml_safer::Write for WrapWrite<'w> {
fn write(&mut self, buffer: &[u8]) -> bool {
match Write::write(self.0, buffer) {
Ok(n) => n != 0,
Err(_) => false,
}
}
}
pub(crate) unsafe fn unsafe_main(
stdin: &mut dyn Read,
stdout: &mut dyn Write,
@ -54,9 +43,7 @@ pub(crate) unsafe fn unsafe_main(
}
let mut emitter = emitter.assume_init();
let mut stdout = WrapWrite(stdout);
yaml_emitter_set_output(&mut emitter, &mut stdout);
yaml_emitter_set_output(&mut emitter, stdout);
yaml_emitter_set_canonical(&mut emitter, false);
yaml_emitter_set_unicode(&mut emitter, false);
@ -126,22 +113,8 @@ pub(crate) unsafe fn unsafe_main(
if result.is_err() {
break Err("Memory error: Not enough memory for creating an event".into());
}
if yaml_emitter_emit(&mut emitter, event).is_err() {
break Err(match emitter.error {
YAML_MEMORY_ERROR => "Memory error: Not enough memory for emitting".into(),
YAML_WRITER_ERROR => format!(
"Writer error: {}",
emitter.problem.unwrap_or("<NO ERROR MESSAGE>")
)
.into(),
YAML_EMITTER_ERROR => format!(
"Emitter error: {}",
emitter.problem.unwrap_or("<NO ERROR MESSAGE>")
)
.into(),
// Couldn't happen.
_ => "Internal error".into(),
});
if let Err(err) = yaml_emitter_emit(&mut emitter, event) {
break Err(err.into());
}
};

View file

@ -2,15 +2,15 @@ use alloc::string::String;
use alloc::vec;
use crate::yaml::{
yaml_anchors_t, yaml_document_t, yaml_emitter_t, yaml_event_t, yaml_node_t, YamlEventData,
YamlNodeData, YAML_ANY_ENCODING,
yaml_anchors_t, yaml_document_t, yaml_emitter_t, yaml_event_t, yaml_node_t, EmitterError,
YamlEventData, YamlNodeData, YAML_ANY_ENCODING,
};
use crate::{libc, yaml_document_delete, yaml_emitter_emit};
/// Start a YAML stream.
///
/// This function should be used before yaml_emitter_dump() is called.
pub fn yaml_emitter_open(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
pub fn yaml_emitter_open(emitter: &mut yaml_emitter_t) -> Result<(), EmitterError> {
__assert!(!emitter.opened);
let event = yaml_event_t {
data: YamlEventData::StreamStart {
@ -26,7 +26,7 @@ pub fn yaml_emitter_open(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
/// Finish a YAML stream.
///
/// This function should be used after yaml_emitter_dump() is called.
pub fn yaml_emitter_close(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
pub fn yaml_emitter_close(emitter: &mut yaml_emitter_t) -> Result<(), EmitterError> {
__assert!(emitter.opened);
if emitter.closed {
return Ok(());
@ -49,11 +49,11 @@ pub fn yaml_emitter_close(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
pub fn yaml_emitter_dump(
emitter: &mut yaml_emitter_t,
document: &mut yaml_document_t,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if !emitter.opened {
if let Err(()) = yaml_emitter_open(emitter) {
if let Err(err) = yaml_emitter_open(emitter) {
yaml_emitter_delete_document_and_anchors(emitter, document);
return Err(());
return Err(err);
}
}
if document.nodes.is_empty() {
@ -156,7 +156,7 @@ fn yaml_emitter_dump_node(
emitter: &mut yaml_emitter_t,
document: &mut yaml_document_t,
index: libc::c_int,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
let node = &mut document.nodes[index as usize - 1];
let anchor_id: libc::c_int = emitter.anchors[index as usize - 1].anchor;
let mut anchor: Option<String> = None;
@ -179,7 +179,10 @@ fn yaml_emitter_dump_node(
}
}
fn yaml_emitter_dump_alias(emitter: &mut yaml_emitter_t, anchor: String) -> Result<(), ()> {
fn yaml_emitter_dump_alias(
emitter: &mut yaml_emitter_t,
anchor: String,
) -> Result<(), EmitterError> {
let event = yaml_event_t {
data: YamlEventData::Alias { anchor },
..Default::default()
@ -191,7 +194,7 @@ fn yaml_emitter_dump_scalar(
emitter: &mut yaml_emitter_t,
node: yaml_node_t,
anchor: Option<String>,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
// TODO: Extract this constant as `YAML_DEFAULT_SCALAR_TAG` (source: dumper.c)
let plain_implicit = node.tag.as_deref() == Some("tag:yaml.org,2002:str");
let quoted_implicit = node.tag.as_deref() == Some("tag:yaml.org,2002:str"); // TODO: Why compare twice?! (even the C code does this)
@ -219,7 +222,7 @@ fn yaml_emitter_dump_sequence(
document: &mut yaml_document_t,
node: yaml_node_t,
anchor: Option<String>,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
// TODO: YAML_DEFAULT_SEQUENCE_TAG
let implicit = node.tag.as_deref() == Some("tag:yaml.org,2002:seq");
@ -253,7 +256,7 @@ fn yaml_emitter_dump_mapping(
document: &mut yaml_document_t,
node: yaml_node_t,
anchor: Option<String>,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
// TODO: YAML_DEFAULT_MAPPING_TAG
let implicit = node.tag.as_deref() == Some("tag:yaml.org,2002:map");

View file

@ -5,12 +5,12 @@ use crate::macros::{
is_alpha, is_ascii, is_blank, is_blankz, is_bom, is_break, is_printable, is_space,
};
use crate::ops::ForceMul as _;
use crate::yaml::YamlEventData;
use crate::yaml::{EmitterError, WriterError, YamlEventData};
use crate::{
libc, yaml_emitter_flush, yaml_emitter_t, yaml_event_delete, yaml_event_t, yaml_scalar_style_t,
yaml_tag_directive_t, yaml_version_directive_t, YAML_ANY_BREAK, YAML_ANY_ENCODING,
YAML_ANY_SCALAR_STYLE, YAML_CRLN_BREAK, YAML_CR_BREAK, YAML_DOUBLE_QUOTED_SCALAR_STYLE,
YAML_EMITTER_ERROR, YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE, YAML_EMIT_BLOCK_MAPPING_KEY_STATE,
YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE, YAML_EMIT_BLOCK_MAPPING_KEY_STATE,
YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE, YAML_EMIT_BLOCK_MAPPING_VALUE_STATE,
YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE, YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE,
YAML_EMIT_DOCUMENT_CONTENT_STATE, YAML_EMIT_DOCUMENT_END_STATE, YAML_EMIT_DOCUMENT_START_STATE,
@ -23,7 +23,7 @@ use crate::{
YAML_SINGLE_QUOTED_SCALAR_STYLE, YAML_UTF8_ENCODING,
};
fn FLUSH(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
fn FLUSH(emitter: &mut yaml_emitter_t) -> Result<(), WriterError> {
if emitter.buffer.len() < OUTPUT_BUFFER_SIZE - 5 {
Ok(())
} else {
@ -31,7 +31,7 @@ fn FLUSH(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
}
}
fn PUT(emitter: &mut yaml_emitter_t, value: u8) -> Result<(), ()> {
fn PUT(emitter: &mut yaml_emitter_t, value: u8) -> Result<(), WriterError> {
FLUSH(emitter)?;
let ch = char::try_from(value).expect("invalid char");
emitter.buffer.push(ch);
@ -39,7 +39,7 @@ fn PUT(emitter: &mut yaml_emitter_t, value: u8) -> Result<(), ()> {
Ok(())
}
fn PUT_BREAK(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
fn PUT_BREAK(emitter: &mut yaml_emitter_t) -> Result<(), WriterError> {
FLUSH(emitter)?;
if emitter.line_break == YAML_CR_BREAK {
emitter.buffer.push('\r');
@ -55,21 +55,21 @@ fn PUT_BREAK(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
/// Write UTF-8 charanters from `string` to `emitter` and increment
/// `emitter.column` the appropriate number of times.
fn WRITE_STR(emitter: &mut yaml_emitter_t, string: &str) -> Result<(), ()> {
fn WRITE_STR(emitter: &mut yaml_emitter_t, string: &str) -> Result<(), WriterError> {
for ch in string.chars() {
WRITE_CHAR(emitter, ch)?;
}
Ok(())
}
fn WRITE_CHAR(emitter: &mut yaml_emitter_t, ch: char) -> Result<(), ()> {
fn WRITE_CHAR(emitter: &mut yaml_emitter_t, ch: char) -> Result<(), WriterError> {
FLUSH(emitter)?;
emitter.buffer.push(ch);
emitter.column += 1;
Ok(())
}
fn WRITE_BREAK_CHAR(emitter: &mut yaml_emitter_t, ch: char) -> Result<(), ()> {
fn WRITE_BREAK_CHAR(emitter: &mut yaml_emitter_t, ch: char) -> Result<(), WriterError> {
FLUSH(emitter)?;
if ch == '\n' {
_ = PUT_BREAK(emitter);
@ -115,13 +115,11 @@ struct ScalarAnalysis<'a> {
pub style: yaml_scalar_style_t,
}
fn yaml_emitter_set_emitter_error(
emitter: &mut yaml_emitter_t,
fn yaml_emitter_set_emitter_error<T>(
_emitter: &mut yaml_emitter_t,
problem: &'static str,
) -> Result<(), ()> {
emitter.error = YAML_EMITTER_ERROR;
emitter.problem = Some(problem);
Err(())
) -> Result<T, EmitterError> {
Err(EmitterError::Problem(problem))
}
/// Emit an event.
@ -130,7 +128,10 @@ fn yaml_emitter_set_emitter_error(
/// 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 yaml_emitter_emit(emitter: &mut yaml_emitter_t, event: yaml_event_t) -> Result<(), ()> {
pub fn yaml_emitter_emit(
emitter: &mut yaml_emitter_t,
event: yaml_event_t,
) -> Result<(), EmitterError> {
emitter.events.push_back(event);
while let Some(mut event) = yaml_emitter_needs_mode_events(emitter) {
let tag_directives = core::mem::take(&mut emitter.tag_directives);
@ -193,7 +194,7 @@ fn yaml_emitter_append_tag_directive(
emitter: &mut yaml_emitter_t,
value: &yaml_tag_directive_t,
allow_duplicates: bool,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
for tag_directive in emitter.tag_directives.iter() {
if value.handle == tag_directive.handle {
if allow_duplicates {
@ -219,7 +220,7 @@ fn yaml_emitter_state_machine(
emitter: &mut yaml_emitter_t,
event: &yaml_event_t,
analysis: &mut Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
match emitter.state {
YAML_EMIT_STREAM_START_STATE => yaml_emitter_emit_stream_start(emitter, event),
YAML_EMIT_FIRST_DOCUMENT_START_STATE => {
@ -275,7 +276,7 @@ fn yaml_emitter_state_machine(
fn yaml_emitter_emit_stream_start(
emitter: &mut yaml_emitter_t,
event: &yaml_event_t,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
emitter.open_ended = 0;
if let YamlEventData::StreamStart { ref encoding } = event.data {
if emitter.encoding == YAML_ANY_ENCODING {
@ -314,7 +315,7 @@ fn yaml_emitter_emit_document_start(
emitter: &mut yaml_emitter_t,
event: &yaml_event_t,
first: bool,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if let YamlEventData::DocumentStart {
version_directive,
tag_directives,
@ -404,7 +405,7 @@ fn yaml_emitter_emit_document_content(
emitter: &mut yaml_emitter_t,
event: &yaml_event_t,
analysis: &mut Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
emitter.states.push(YAML_EMIT_DOCUMENT_END_STATE);
yaml_emitter_emit_node(emitter, event, true, false, false, false, analysis)
}
@ -412,7 +413,7 @@ fn yaml_emitter_emit_document_content(
fn yaml_emitter_emit_document_end(
emitter: &mut yaml_emitter_t,
event: &yaml_event_t,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if let YamlEventData::DocumentEnd { implicit } = &event.data {
let implicit = *implicit;
yaml_emitter_write_indent(emitter)?;
@ -437,7 +438,7 @@ fn yaml_emitter_emit_flow_sequence_item(
event: &yaml_event_t,
first: bool,
analysis: &mut Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if first {
yaml_emitter_write_indicator(emitter, "[", true, true, false)?;
yaml_emitter_increase_indent(emitter, true, false);
@ -469,7 +470,7 @@ fn yaml_emitter_emit_flow_mapping_key(
event: &yaml_event_t,
first: bool,
analysis: &mut Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if first {
yaml_emitter_write_indicator(emitter, "{", true, true, false)?;
yaml_emitter_increase_indent(emitter, true, false);
@ -477,7 +478,7 @@ fn yaml_emitter_emit_flow_mapping_key(
}
if let YamlEventData::MappingEnd = &event.data {
if emitter.indents.is_empty() {
return Err(());
panic!("emitter.indents should not be empty");
}
emitter.flow_level -= 1;
emitter.indent = emitter.indents.pop().unwrap();
@ -512,7 +513,7 @@ fn yaml_emitter_emit_flow_mapping_value(
event: &yaml_event_t,
simple: bool,
analysis: &mut Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if simple {
yaml_emitter_write_indicator(emitter, ":", false, false, false)?;
} else {
@ -530,7 +531,7 @@ fn yaml_emitter_emit_block_sequence_item(
event: &yaml_event_t,
first: bool,
analysis: &mut Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if first {
yaml_emitter_increase_indent(
emitter,
@ -554,7 +555,7 @@ fn yaml_emitter_emit_block_mapping_key(
event: &yaml_event_t,
first: bool,
analysis: &mut Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if first {
yaml_emitter_increase_indent(emitter, false, false);
}
@ -581,7 +582,7 @@ fn yaml_emitter_emit_block_mapping_value(
event: &yaml_event_t,
simple: bool,
analysis: &mut Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if simple {
yaml_emitter_write_indicator(emitter, ":", false, false, false)?;
} else {
@ -600,7 +601,7 @@ fn yaml_emitter_emit_node(
mapping: bool,
simple_key: bool,
analysis: &mut Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
emitter.root_context = root;
emitter.sequence_context = sequence;
emitter.mapping_context = mapping;
@ -626,7 +627,7 @@ fn yaml_emitter_emit_alias(
emitter: &mut yaml_emitter_t,
_event: &yaml_event_t,
analysis: &Option<AnchorAnalysis>,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
yaml_emitter_process_anchor(emitter, analysis)?;
if emitter.simple_key_context {
PUT(emitter, b' ')?;
@ -639,7 +640,7 @@ fn yaml_emitter_emit_scalar(
emitter: &mut yaml_emitter_t,
event: &yaml_event_t,
analysis: &mut Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
let Analysis {
anchor,
tag,
@ -663,7 +664,7 @@ fn yaml_emitter_emit_sequence_start(
emitter: &mut yaml_emitter_t,
event: &yaml_event_t,
analysis: &Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
let Analysis { anchor, tag, .. } = analysis;
yaml_emitter_process_anchor(emitter, anchor)?;
yaml_emitter_process_tag(emitter, tag)?;
@ -690,7 +691,7 @@ fn yaml_emitter_emit_mapping_start(
emitter: &mut yaml_emitter_t,
event: &yaml_event_t,
analysis: &Analysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
let Analysis { anchor, tag, .. } = analysis;
yaml_emitter_process_anchor(emitter, anchor)?;
yaml_emitter_process_tag(emitter, tag)?;
@ -811,7 +812,7 @@ fn yaml_emitter_select_scalar_style(
event: &yaml_event_t,
scalar_analysis: &mut ScalarAnalysis,
tag_analysis: &mut Option<TagAnalysis>,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if let YamlEventData::Scalar {
plain_implicit,
quoted_implicit,
@ -880,7 +881,7 @@ fn yaml_emitter_select_scalar_style(
fn yaml_emitter_process_anchor(
emitter: &mut yaml_emitter_t,
analysis: &Option<AnchorAnalysis>,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
let Some(analysis) = analysis.as_ref() else {
return Ok(());
};
@ -897,7 +898,7 @@ fn yaml_emitter_process_anchor(
fn yaml_emitter_process_tag(
emitter: &mut yaml_emitter_t,
analysis: &Option<TagAnalysis>,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
let Some(analysis) = analysis.as_ref() else {
return Ok(());
};
@ -921,7 +922,7 @@ fn yaml_emitter_process_tag(
fn yaml_emitter_process_scalar(
emitter: &mut yaml_emitter_t,
analysis: &ScalarAnalysis,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
match analysis.style {
YAML_PLAIN_SCALAR_STYLE => {
return yaml_emitter_write_plain_scalar(
@ -950,15 +951,14 @@ fn yaml_emitter_process_scalar(
YAML_FOLDED_SCALAR_STYLE => {
return yaml_emitter_write_folded_scalar(emitter, analysis.value);
}
_ => {}
YAML_ANY_SCALAR_STYLE => unreachable!("No scalar style chosen"),
}
Err(())
}
fn yaml_emitter_analyze_version_directive(
emitter: &mut yaml_emitter_t,
version_directive: &yaml_version_directive_t,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if version_directive.major != 1 || version_directive.minor != 1 && version_directive.minor != 2
{
return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive");
@ -969,7 +969,7 @@ fn yaml_emitter_analyze_version_directive(
fn yaml_emitter_analyze_tag_directive(
emitter: &mut yaml_emitter_t,
tag_directive: &yaml_tag_directive_t,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if tag_directive.handle.is_empty() {
return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty");
}
@ -1002,7 +1002,7 @@ fn yaml_emitter_analyze_anchor<'a>(
emitter: &mut yaml_emitter_t,
anchor: &'a str,
alias: bool,
) -> Result<AnchorAnalysis<'a>, ()> {
) -> Result<AnchorAnalysis<'a>, EmitterError> {
if anchor.is_empty() {
yaml_emitter_set_emitter_error(
emitter,
@ -1034,7 +1034,7 @@ fn yaml_emitter_analyze_tag<'a>(
emitter: &mut yaml_emitter_t,
tag: &'a str,
tag_directives: &'a [yaml_tag_directive_t],
) -> Result<TagAnalysis<'a>, ()> {
) -> Result<TagAnalysis<'a>, EmitterError> {
if tag.is_empty() {
yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")?;
}
@ -1057,7 +1057,7 @@ fn yaml_emitter_analyze_tag<'a>(
fn yaml_emitter_analyze_scalar<'a>(
emitter: &mut yaml_emitter_t,
value: &'a str,
) -> Result<ScalarAnalysis<'a>, ()> {
) -> Result<ScalarAnalysis<'a>, EmitterError> {
let mut block_indicators = false;
let mut flow_indicators = false;
let mut line_breaks = false;
@ -1224,7 +1224,7 @@ fn yaml_emitter_analyze_event<'a>(
emitter: &mut yaml_emitter_t,
event: &'a yaml_event_t,
tag_directives: &'a [yaml_tag_directive_t],
) -> Result<Analysis<'a>, ()> {
) -> Result<Analysis<'a>, EmitterError> {
let mut analysis = Analysis::default();
match &event.data {
@ -1292,13 +1292,13 @@ fn yaml_emitter_analyze_event<'a>(
Ok(analysis)
}
fn yaml_emitter_write_bom(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
fn yaml_emitter_write_bom(emitter: &mut yaml_emitter_t) -> Result<(), EmitterError> {
FLUSH(emitter)?;
emitter.buffer.push('\u{feff}');
Ok(())
}
fn yaml_emitter_write_indent(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
fn yaml_emitter_write_indent(emitter: &mut yaml_emitter_t) -> Result<(), EmitterError> {
let indent: libc::c_int = if emitter.indent >= 0 {
emitter.indent
} else {
@ -1324,7 +1324,7 @@ fn yaml_emitter_write_indicator(
need_whitespace: bool,
is_whitespace: bool,
is_indention: bool,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if need_whitespace && !emitter.whitespace {
PUT(emitter, b' ')?;
}
@ -1334,14 +1334,20 @@ fn yaml_emitter_write_indicator(
Ok(())
}
fn yaml_emitter_write_anchor(emitter: &mut yaml_emitter_t, value: &str) -> Result<(), ()> {
fn yaml_emitter_write_anchor(
emitter: &mut yaml_emitter_t,
value: &str,
) -> Result<(), EmitterError> {
WRITE_STR(emitter, value)?;
emitter.whitespace = false;
emitter.indention = false;
Ok(())
}
fn yaml_emitter_write_tag_handle(emitter: &mut yaml_emitter_t, value: &str) -> Result<(), ()> {
fn yaml_emitter_write_tag_handle(
emitter: &mut yaml_emitter_t,
value: &str,
) -> Result<(), EmitterError> {
if !emitter.whitespace {
PUT(emitter, b' ')?;
}
@ -1355,7 +1361,7 @@ fn yaml_emitter_write_tag_content(
emitter: &mut yaml_emitter_t,
value: &str,
need_whitespace: bool,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
if need_whitespace && !emitter.whitespace {
PUT(emitter, b' ')?;
}
@ -1396,7 +1402,7 @@ fn yaml_emitter_write_plain_scalar(
emitter: &mut yaml_emitter_t,
value: &str,
allow_breaks: bool,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
let mut spaces = false;
let mut breaks = false;
if !emitter.whitespace && (!value.is_empty() || emitter.flow_level != 0) {
@ -1440,7 +1446,7 @@ fn yaml_emitter_write_single_quoted_scalar(
emitter: &mut yaml_emitter_t,
value: &str,
allow_breaks: bool,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
let mut spaces = false;
let mut breaks = false;
yaml_emitter_write_indicator(emitter, "'", true, false, false)?;
@ -1498,7 +1504,7 @@ fn yaml_emitter_write_double_quoted_scalar(
emitter: &mut yaml_emitter_t,
value: &str,
allow_breaks: bool,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
let mut spaces = false;
yaml_emitter_write_indicator(emitter, "\"", true, false, false)?;
let mut chars = value.chars();
@ -1615,7 +1621,7 @@ fn yaml_emitter_write_double_quoted_scalar(
fn yaml_emitter_write_block_scalar_hints(
emitter: &mut yaml_emitter_t,
string: &str,
) -> Result<(), ()> {
) -> Result<(), EmitterError> {
let mut chomp_hint: Option<&str> = None;
let first = string.chars().next();
@ -1655,7 +1661,10 @@ fn yaml_emitter_write_block_scalar_hints(
Ok(())
}
fn yaml_emitter_write_literal_scalar(emitter: &mut yaml_emitter_t, value: &str) -> Result<(), ()> {
fn yaml_emitter_write_literal_scalar(
emitter: &mut yaml_emitter_t,
value: &str,
) -> Result<(), EmitterError> {
let mut breaks = true;
yaml_emitter_write_indicator(emitter, "|", true, false, false)?;
yaml_emitter_write_block_scalar_hints(emitter, value)?;
@ -1680,7 +1689,10 @@ fn yaml_emitter_write_literal_scalar(emitter: &mut yaml_emitter_t, value: &str)
Ok(())
}
fn yaml_emitter_write_folded_scalar(emitter: &mut yaml_emitter_t, value: &str) -> Result<(), ()> {
fn yaml_emitter_write_folded_scalar(
emitter: &mut yaml_emitter_t,
value: &str,
) -> Result<(), EmitterError> {
let mut breaks = true;
let mut leading_spaces = true;
yaml_emitter_write_indicator(emitter, ">", true, false, false)?;

View file

@ -4,7 +4,6 @@
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
#![no_std]
#![doc(html_root_url = "https://docs.rs/unsafe-libyaml/0.2.10")]
#![allow(non_camel_case_types, non_snake_case, unsafe_op_in_unsafe_fn)]
#![warn(clippy::pedantic)]
@ -150,7 +149,7 @@ pub use crate::yaml::{
yaml_node_item_t, yaml_node_pair_t, yaml_node_t, yaml_parser_state_t, yaml_parser_t,
yaml_read_handler_t, yaml_scalar_style_t, yaml_sequence_style_t, yaml_simple_key_t,
yaml_tag_directive_t, yaml_token_t, yaml_token_type_t, yaml_version_directive_t,
yaml_write_handler_t, Read, Write, YamlEventData,
yaml_write_handler_t, YamlEventData,
};
#[doc(hidden)]
pub use crate::yaml::{
@ -161,6 +160,8 @@ pub use crate::yaml::{
#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use super::*;
#[test]
@ -269,7 +270,7 @@ tie-fighter: '|\-*-/|'
fn integration_hs5t() {
unsafe {
let mut emitter = emitter_new();
let mut output = alloc::string::String::new();
let mut output = Vec::new();
yaml_emitter_set_output_string(&mut emitter, &mut output);
let mut event = yaml_event_t::default();
@ -293,7 +294,10 @@ tie-fighter: '|\-*-/|'
yaml_stream_end_event_initialize(&mut event).unwrap();
yaml_emitter_emit(&mut emitter, core::mem::take(&mut event)).unwrap();
assert_eq!(output, "'1st non-empty\n\n 2nd non-empty 3rd non-empty'\n");
assert_eq!(
core::str::from_utf8(&output),
Ok("'1st non-empty\n\n 2nd non-empty 3rd non-empty'\n")
);
}
}

View file

@ -1,37 +1,32 @@
use crate::yaml::WriterError;
use crate::yaml_encoding_t::YAML_UTF16BE_ENCODING;
use crate::{
yaml_emitter_t, YAML_ANY_ENCODING, YAML_UTF16LE_ENCODING, YAML_UTF8_ENCODING, YAML_WRITER_ERROR,
};
fn yaml_emitter_set_writer_error(
emitter: &mut yaml_emitter_t,
problem: &'static str,
) -> Result<(), ()> {
emitter.error = YAML_WRITER_ERROR;
emitter.problem = Some(problem);
Err(())
}
use crate::{yaml_emitter_t, YAML_ANY_ENCODING, YAML_UTF16LE_ENCODING, YAML_UTF8_ENCODING};
/// Flush the accumulated characters to the output.
pub fn yaml_emitter_flush(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
pub fn yaml_emitter_flush(emitter: &mut yaml_emitter_t) -> Result<(), WriterError> {
__assert!((emitter.write_handler).is_some());
__assert!(emitter.encoding != YAML_ANY_ENCODING);
if emitter.buffer.is_empty() {
return Ok(());
}
// TODO: Support partial writes. These calls fail unless the writer is able
// to write absolutely everything in the buffer.
if emitter.encoding == YAML_UTF8_ENCODING {
let to_emit = emitter.buffer.as_bytes();
if emitter
.write_handler
.as_mut()
.expect("non-null function pointer")
.write(to_emit)
.expect("non-null writer")
.write(to_emit)?
== to_emit.len()
{
emitter.buffer.clear();
return Ok(());
} else {
return yaml_emitter_set_writer_error(emitter, "write error");
return Err(WriterError::Incomplete);
}
}
@ -56,12 +51,13 @@ pub fn yaml_emitter_flush(emitter: &mut yaml_emitter_t) -> Result<(), ()> {
.write_handler
.as_mut()
.expect("non-null function pointer")
.write(to_emit)
.write(to_emit)?
== to_emit.len()
{
emitter.buffer.clear();
emitter.raw_buffer.clear();
Ok(())
} else {
yaml_emitter_set_writer_error(emitter, "write error")
return Err(WriterError::Incomplete);
}
}

View file

@ -86,6 +86,22 @@ pub enum yaml_error_type_t {
YAML_EMITTER_ERROR = 7,
}
#[derive(Debug, thiserror::Error)]
pub enum EmitterError {
#[error("{0}")]
Problem(&'static str),
#[error(transparent)]
Writer(#[from] WriterError),
}
#[derive(Debug, thiserror::Error)]
pub enum WriterError {
#[error("writer could not flush the entire buffer")]
Incomplete,
#[error(transparent)]
Io(#[from] std::io::Error),
}
/// The pointer position.
#[derive(Copy, Clone, Default, Debug)]
#[repr(C)]
@ -872,12 +888,8 @@ pub(crate) struct yaml_anchors_t {
#[repr(C)]
#[non_exhaustive]
pub struct yaml_emitter_t<'w> {
/// Error type.
pub error: yaml_error_type_t,
/// Error description.
pub problem: Option<&'static str>,
/// Write handler.
pub(crate) write_handler: Option<&'w mut dyn Write>,
pub(crate) write_handler: Option<&'w mut dyn std::io::Write>,
/// Standard (string or file) output data.
pub(crate) output: unnamed_yaml_emitter_t_output_string,
/// The working buffer.
@ -947,8 +959,6 @@ pub struct yaml_emitter_t<'w> {
impl<'a> Default for yaml_emitter_t<'a> {
fn default() -> Self {
Self {
error: Default::default(),
problem: Default::default(),
write_handler: None,
output: Default::default(),
buffer: Default::default(),
@ -1002,31 +1012,3 @@ impl Default for unnamed_yaml_emitter_t_output_string {
}
}
}
pub trait Write {
fn write(&mut self, buffer: &[u8]) -> bool;
}
pub trait Read {
fn read(&mut self, buffer: &mut [u8]) -> usize;
}
impl Write for Vec<u8> {
fn write(&mut self, buffer: &[u8]) -> bool {
self.extend(buffer);
true
}
}
impl Write for String {
fn write(&mut self, buffer: &[u8]) -> bool {
self.push_str(core::str::from_utf8(buffer).expect("invalid UTF-8"));
true
}
}
impl Write for &mut &mut [u8] {
fn write(&mut self, buffer: &[u8]) -> bool {
todo!()
}
}