Rustify module organization

This commit is contained in:
Simon Ask Ulsnes 2024-02-04 10:03:36 +01:00
parent 1ffb036601
commit 5b9dcd7a15
12 changed files with 1183 additions and 1233 deletions

View file

@ -1,516 +0,0 @@
use alloc::string::String;
use alloc::vec::Vec;
use crate::yaml::{EventData, NodeData};
use crate::{
Break, Document, Emitter, EmitterState, Encoding, Event, MappingStyle, Mark, Node, NodePair,
Parser, ParserState, ScalarStyle, SequenceStyle, TagDirective, VersionDirective,
DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG,
};
use std::collections::VecDeque;
pub(crate) const INPUT_RAW_BUFFER_SIZE: usize = 16384;
pub(crate) const INPUT_BUFFER_SIZE: usize = INPUT_RAW_BUFFER_SIZE;
pub(crate) const OUTPUT_BUFFER_SIZE: usize = 16384;
/// Create a parser.
pub fn yaml_parser_new<'r>() -> Parser<'r> {
Parser {
read_handler: None,
eof: false,
buffer: VecDeque::with_capacity(INPUT_BUFFER_SIZE),
unread: 0,
encoding: Encoding::Any,
offset: 0,
mark: Mark::default(),
stream_start_produced: false,
stream_end_produced: false,
flow_level: 0,
tokens: VecDeque::with_capacity(16),
tokens_parsed: 0,
token_available: false,
indents: Vec::with_capacity(16),
indent: 0,
simple_key_allowed: false,
simple_keys: Vec::with_capacity(16),
states: Vec::with_capacity(16),
state: ParserState::default(),
marks: Vec::with_capacity(16),
tag_directives: Vec::with_capacity(16),
aliases: Vec::new(),
}
}
/// Reset the parser state.
pub fn yaml_parser_reset(parser: &mut Parser) {
*parser = yaml_parser_new();
}
/// Set a string input.
pub fn yaml_parser_set_input_string<'r>(parser: &mut Parser<'r>, input: &'r mut &[u8]) {
assert!((parser.read_handler).is_none());
parser.read_handler = Some(input);
}
/// Set a generic input handler.
pub fn yaml_parser_set_input<'r>(parser: &mut Parser<'r>, input: &'r mut dyn std::io::BufRead) {
assert!((parser.read_handler).is_none());
parser.read_handler = Some(input);
}
/// Set the source encoding.
pub fn yaml_parser_set_encoding(parser: &mut Parser, encoding: Encoding) {
assert!(parser.encoding == Encoding::Any);
parser.encoding = encoding;
}
/// Create an emitter.
pub fn yaml_emitter_new<'w>() -> Emitter<'w> {
Emitter {
write_handler: None,
buffer: String::with_capacity(OUTPUT_BUFFER_SIZE),
raw_buffer: Vec::with_capacity(OUTPUT_BUFFER_SIZE),
encoding: Encoding::Any,
canonical: false,
best_indent: 0,
best_width: 0,
unicode: false,
line_break: Break::default(),
states: Vec::with_capacity(16),
state: EmitterState::default(),
events: VecDeque::with_capacity(16),
indents: Vec::with_capacity(16),
tag_directives: Vec::with_capacity(16),
indent: 0,
flow_level: 0,
root_context: false,
sequence_context: false,
mapping_context: false,
simple_key_context: false,
line: 0,
column: 0,
whitespace: false,
indention: false,
open_ended: 0,
opened: false,
closed: false,
anchors: Vec::new(),
last_anchor_id: 0,
}
}
/// Reset the emitter state.
pub fn yaml_emitter_reset(emitter: &mut Emitter) {
*emitter = yaml_emitter_new();
}
/// Set a string output.
///
/// The emitter will write the output characters to the `output` buffer.
pub fn yaml_emitter_set_output_string<'w>(emitter: &mut Emitter<'w>, output: &'w mut Vec<u8>) {
assert!(emitter.write_handler.is_none());
if emitter.encoding == Encoding::Any {
yaml_emitter_set_encoding(emitter, Encoding::Utf8);
} else if emitter.encoding != Encoding::Utf8 {
panic!("cannot output UTF-16 to String")
}
output.clear();
emitter.write_handler = Some(output);
}
/// Set a generic output handler.
pub fn yaml_emitter_set_output<'w>(emitter: &mut Emitter<'w>, handler: &'w mut dyn std::io::Write) {
assert!(emitter.write_handler.is_none());
emitter.write_handler = Some(handler);
}
/// Set the output encoding.
pub fn yaml_emitter_set_encoding(emitter: &mut Emitter, encoding: Encoding) {
assert_eq!(emitter.encoding, Encoding::Any);
emitter.encoding = encoding;
}
/// Set if the output should be in the "canonical" format as in the YAML
/// specification.
pub fn yaml_emitter_set_canonical(emitter: &mut Emitter, canonical: bool) {
emitter.canonical = canonical;
}
/// Set the indentation increment.
pub fn yaml_emitter_set_indent(emitter: &mut Emitter, indent: i32) {
emitter.best_indent = if 1 < indent && indent < 10 { indent } else { 2 };
}
/// Set the preferred line width. -1 means unlimited.
pub fn yaml_emitter_set_width(emitter: &mut Emitter, width: i32) {
emitter.best_width = if width >= 0 { width } else { -1 };
}
/// Set if unescaped non-ASCII characters are allowed.
pub fn yaml_emitter_set_unicode(emitter: &mut Emitter, unicode: bool) {
emitter.unicode = unicode;
}
/// Set the preferred line break.
pub fn yaml_emitter_set_break(emitter: &mut Emitter, line_break: Break) {
emitter.line_break = line_break;
}
/// Create the STREAM-START event.
pub fn yaml_stream_start_event_new(encoding: Encoding) -> Event {
Event {
data: EventData::StreamStart { encoding },
..Default::default()
}
}
/// Create the STREAM-END event.
pub fn yaml_stream_end_event_new() -> Event {
Event {
data: EventData::StreamEnd,
..Default::default()
}
}
/// Create the DOCUMENT-START event.
///
/// The `implicit` argument is considered as a stylistic parameter and may be
/// ignored by the emitter.
pub fn yaml_document_start_event_new(
version_directive: Option<VersionDirective>,
tag_directives_in: &[TagDirective],
implicit: bool,
) -> Event {
let tag_directives = tag_directives_in.to_vec();
Event {
data: EventData::DocumentStart {
version_directive,
tag_directives,
implicit,
},
..Default::default()
}
}
/// Create the DOCUMENT-END event.
///
/// The `implicit` argument is considered as a stylistic parameter and may be
/// ignored by the emitter.
pub fn yaml_document_end_event_new(implicit: bool) -> Event {
Event {
data: EventData::DocumentEnd { implicit },
..Default::default()
}
}
/// Create an ALIAS event.
pub fn yaml_alias_event_new(anchor: &str) -> Event {
Event {
data: EventData::Alias {
anchor: String::from(anchor),
},
..Default::default()
}
}
/// Create a SCALAR event.
///
/// The `style` argument may be ignored by the emitter.
///
/// Either the `tag` attribute or one of the `plain_implicit` and
/// `quoted_implicit` flags must be set.
///
pub fn yaml_scalar_event_new(
anchor: Option<&str>,
tag: Option<&str>,
value: &str,
plain_implicit: bool,
quoted_implicit: bool,
style: ScalarStyle,
) -> Event {
let mark = Mark {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let mut anchor_copy: Option<String> = None;
let mut tag_copy: Option<String> = None;
if let Some(anchor) = anchor {
anchor_copy = Some(String::from(anchor));
}
if let Some(tag) = tag {
tag_copy = Some(String::from(tag));
}
Event {
data: EventData::Scalar {
anchor: anchor_copy,
tag: tag_copy,
value: String::from(value),
plain_implicit,
quoted_implicit,
style,
},
start_mark: mark,
end_mark: mark,
}
}
/// Create a SEQUENCE-START event.
///
/// The `style` argument may be ignored by the emitter.
///
/// Either the `tag` attribute or the `implicit` flag must be set.
pub fn yaml_sequence_start_event_new(
anchor: Option<&str>,
tag: Option<&str>,
implicit: bool,
style: SequenceStyle,
) -> Event {
let mut anchor_copy: Option<String> = None;
let mut tag_copy: Option<String> = None;
if let Some(anchor) = anchor {
anchor_copy = Some(String::from(anchor));
}
if let Some(tag) = tag {
tag_copy = Some(String::from(tag));
}
Event {
data: EventData::SequenceStart {
anchor: anchor_copy,
tag: tag_copy,
implicit,
style,
},
..Default::default()
}
}
/// Create a SEQUENCE-END event.
pub fn yaml_sequence_end_event_new() -> Event {
Event {
data: EventData::SequenceEnd,
..Default::default()
}
}
/// Create a MAPPING-START event.
///
/// The `style` argument may be ignored by the emitter.
///
/// Either the `tag` attribute or the `implicit` flag must be set.
pub fn yaml_mapping_start_event_new(
anchor: Option<&str>,
tag: Option<&str>,
implicit: bool,
style: MappingStyle,
) -> Event {
let mut anchor_copy: Option<String> = None;
let mut tag_copy: Option<String> = None;
if let Some(anchor) = anchor {
anchor_copy = Some(String::from(anchor));
}
if let Some(tag) = tag {
tag_copy = Some(String::from(tag));
}
Event {
data: EventData::MappingStart {
anchor: anchor_copy,
tag: tag_copy,
implicit,
style,
},
..Default::default()
}
}
/// Create a MAPPING-END event.
pub fn yaml_mapping_end_event_new() -> Event {
Event {
data: EventData::MappingEnd,
..Default::default()
}
}
/// Create a YAML document.
pub fn yaml_document_new(
version_directive: Option<VersionDirective>,
tag_directives_in: &[TagDirective],
start_implicit: bool,
end_implicit: bool,
) -> Document {
let nodes = Vec::with_capacity(16);
let tag_directives = tag_directives_in.to_vec();
Document {
nodes,
version_directive,
tag_directives,
start_implicit,
end_implicit,
start_mark: Mark::default(),
end_mark: Mark::default(),
}
}
/// Delete a YAML document and all its nodes.
pub fn yaml_document_delete(document: &mut Document) {
document.nodes.clear();
document.version_directive = None;
document.tag_directives.clear();
}
/// Get a node of a YAML document.
///
/// Returns the node object or `None` if `index` is out of range.
pub fn yaml_document_get_node(document: &mut Document, index: i32) -> Option<&mut Node> {
document.nodes.get_mut(index as usize - 1)
}
/// Get the root of a YAML document node.
///
/// The root object is the first object added to the document.
///
/// An empty document produced by the parser signifies the end of a YAML stream.
///
/// Returns the node object or `None` if the document is empty.
pub fn yaml_document_get_root_node(document: &mut Document) -> Option<&mut Node> {
document.nodes.get_mut(0)
}
/// Create a SCALAR node and attach it to the document.
///
/// The `style` argument may be ignored by the emitter.
///
/// Returns the node id or 0 on error.
#[must_use]
pub fn yaml_document_add_scalar(
document: &mut Document,
tag: Option<&str>,
value: &str,
style: ScalarStyle,
) -> i32 {
let mark = Mark {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let tag = tag.unwrap_or(DEFAULT_SCALAR_TAG);
let tag_copy = String::from(tag);
let value_copy = String::from(value);
let node = Node {
data: NodeData::Scalar {
value: value_copy,
style,
},
tag: Some(tag_copy),
start_mark: mark,
end_mark: mark,
};
document.nodes.push(node);
document.nodes.len() as i32
}
/// Create a SEQUENCE node and attach it to the document.
///
/// The `style` argument may be ignored by the emitter.
///
/// Returns the node id, which is a nonzero integer.
#[must_use]
pub fn yaml_document_add_sequence(
document: &mut Document,
tag: Option<&str>,
style: SequenceStyle,
) -> i32 {
let mark = Mark {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let items = Vec::with_capacity(16);
let tag = tag.unwrap_or(DEFAULT_SEQUENCE_TAG);
let tag_copy = String::from(tag);
let node = Node {
data: NodeData::Sequence { items, style },
tag: Some(tag_copy),
start_mark: mark,
end_mark: mark,
};
document.nodes.push(node);
document.nodes.len() as i32
}
/// Create a MAPPING node and attach it to the document.
///
/// The `style` argument may be ignored by the emitter.
///
/// Returns the node id, which is a nonzero integer.
#[must_use]
pub fn yaml_document_add_mapping(
document: &mut Document,
tag: Option<&str>,
style: MappingStyle,
) -> i32 {
let mark = Mark {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let pairs = Vec::with_capacity(16);
let tag = tag.unwrap_or(DEFAULT_MAPPING_TAG);
let tag_copy = String::from(tag);
let node = Node {
data: NodeData::Mapping { pairs, style },
tag: Some(tag_copy),
start_mark: mark,
end_mark: mark,
};
document.nodes.push(node);
document.nodes.len() as i32
}
/// Add an item to a SEQUENCE node.
pub fn yaml_document_append_sequence_item(document: &mut Document, sequence: i32, item: i32) {
assert!(sequence > 0 && sequence as usize - 1 < document.nodes.len());
assert!(matches!(
&document.nodes[sequence as usize - 1].data,
NodeData::Sequence { .. }
));
assert!(item > 0 && item as usize - 1 < document.nodes.len());
if let NodeData::Sequence { ref mut items, .. } =
&mut document.nodes[sequence as usize - 1].data
{
items.push(item);
}
}
/// Add a pair of a key and a value to a MAPPING node.
pub fn yaml_document_append_mapping_pair(
document: &mut Document,
mapping: i32,
key: i32,
value: i32,
) {
assert!(mapping > 0 && mapping as usize - 1 < document.nodes.len());
assert!(matches!(
&document.nodes[mapping as usize - 1].data,
NodeData::Mapping { .. }
));
assert!(key > 0 && key as usize - 1 < document.nodes.len());
assert!(value > 0 && value as usize - 1 < document.nodes.len());
let pair = NodePair { key, value };
if let NodeData::Mapping { ref mut pairs, .. } = &mut document.nodes[mapping as usize - 1].data
{
pairs.push(pair);
}
}

View file

@ -16,12 +16,9 @@
)]
use libyaml_safer::{
yaml_alias_event_new, yaml_document_end_event_new, yaml_document_start_event_new,
yaml_emitter_emit, yaml_emitter_new, yaml_emitter_reset, yaml_emitter_set_canonical,
yaml_emitter_set_output, yaml_emitter_set_unicode, yaml_mapping_end_event_new,
yaml_mapping_start_event_new, yaml_scalar_event_new, yaml_sequence_end_event_new,
yaml_sequence_start_event_new, yaml_stream_end_event_new, yaml_stream_start_event_new,
Encoding, MappingStyle, ScalarStyle, SequenceStyle,
yaml_emitter_set_output, yaml_emitter_set_unicode, Encoding, Event, MappingStyle, ScalarStyle,
SequenceStyle,
};
use std::env;
use std::error::Error;
@ -52,38 +49,38 @@ pub(crate) fn test_main(
let line = line_buffer.strip_suffix('\n').unwrap_or(&line_buffer);
let event = if line.starts_with("+STR") {
yaml_stream_start_event_new(Encoding::Utf8)
Event::stream_start(Encoding::Utf8)
} else if line.starts_with("-STR") {
yaml_stream_end_event_new()
Event::stream_end()
} else if line.starts_with("+DOC") {
let implicit = !line[4..].starts_with(" ---");
yaml_document_start_event_new(None, &[], implicit)
Event::document_start(None, &[], implicit)
} else if line.starts_with("-DOC") {
let implicit = !line[4..].starts_with(" ...");
yaml_document_end_event_new(implicit)
Event::document_end(implicit)
} else if line.starts_with("+MAP") {
yaml_mapping_start_event_new(
Event::mapping_start(
get_anchor('&', line),
get_tag(line),
false,
MappingStyle::Block,
)
} else if line.starts_with("-MAP") {
yaml_mapping_end_event_new()
Event::mapping_end()
} else if line.starts_with("+SEQ") {
yaml_sequence_start_event_new(
Event::sequence_start(
get_anchor('&', line),
get_tag(line),
false,
SequenceStyle::Block,
)
} else if line.starts_with("-SEQ") {
yaml_sequence_end_event_new()
Event::sequence_end()
} else if line.starts_with("=VAL") {
let mut style = ScalarStyle::Any;
let value = get_value(line, &mut value_buffer, &mut style);
let implicit = get_tag(line).is_none();
yaml_scalar_event_new(
Event::scalar(
get_anchor('&', line),
get_tag(line),
value,
@ -92,7 +89,7 @@ pub(crate) fn test_main(
style,
)
} else if line.starts_with("=ALI") {
yaml_alias_event_new(get_anchor('*', line).expect("no alias name"))
Event::alias(get_anchor('*', line).expect("no alias name"))
} else {
break Err(format!("Unknown event: '{line}'").into());
};

244
src/document.rs Normal file
View file

@ -0,0 +1,244 @@
use crate::{
MappingStyle, Mark, ScalarStyle, SequenceStyle, TagDirective, VersionDirective,
DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG,
};
/// The document structure.
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Document {
/// The document nodes.
pub nodes: Vec<Node>,
/// The version directive.
pub version_directive: Option<VersionDirective>,
/// The list of tag directives.
///
/// ```
/// # const _: &str = stringify! {
/// struct {
/// /// The beginning of the tag directives list.
/// start: *mut yaml_tag_directive_t,
/// /// The end of the tag directives list.
/// end: *mut yaml_tag_directive_t,
/// }
/// # };
/// ```
pub tag_directives: Vec<TagDirective>,
/// Is the document start indicator implicit?
pub start_implicit: bool,
/// Is the document end indicator implicit?
pub end_implicit: bool,
/// The beginning of the document.
pub start_mark: Mark,
/// The end of the document.
pub end_mark: Mark,
}
/// The node structure.
#[derive(Clone, Default, Debug)]
#[non_exhaustive]
pub struct Node {
/// The node type.
pub data: NodeData,
/// The node tag.
pub tag: Option<String>,
/// The beginning of the node.
pub start_mark: Mark,
/// The end of the node.
pub end_mark: Mark,
}
/// Node types.
#[derive(Clone, Default, Debug)]
pub enum NodeData {
/// An empty node.
#[default]
NoNode,
/// A scalar node.
Scalar {
/// The scalar value.
value: String,
/// The scalar style.
style: ScalarStyle,
},
/// A sequence node.
Sequence {
/// The stack of sequence items.
items: Vec<NodeItem>,
/// The sequence style.
style: SequenceStyle,
},
/// A mapping node.
Mapping {
/// The stack of mapping pairs (key, value).
pairs: Vec<NodePair>,
/// The mapping style.
style: MappingStyle,
},
}
/// An element of a sequence node.
pub type NodeItem = i32;
/// An element of a mapping node.
#[derive(Copy, Clone, Default, Debug)]
#[non_exhaustive]
pub struct NodePair {
/// The key of the element.
pub key: i32,
/// The value of the element.
pub value: i32,
}
impl Document {
/// Create a YAML document.
pub fn new(
version_directive: Option<VersionDirective>,
tag_directives_in: &[TagDirective],
start_implicit: bool,
end_implicit: bool,
) -> Document {
let nodes = Vec::with_capacity(16);
let tag_directives = tag_directives_in.to_vec();
Document {
nodes,
version_directive,
tag_directives,
start_implicit,
end_implicit,
start_mark: Mark::default(),
end_mark: Mark::default(),
}
}
/// Get a node of a YAML document.
///
/// Returns the node object or `None` if `index` is out of range.
pub fn get_node(&mut self, index: i32) -> Option<&mut Node> {
self.nodes.get_mut(index as usize - 1)
}
/// Get the root of a YAML document node.
///
/// The root object is the first object added to the document.
///
/// An empty document produced by the parser signifies the end of a YAML stream.
///
/// Returns the node object or `None` if the document is empty.
pub fn get_root_node(&mut self) -> Option<&mut Node> {
self.nodes.get_mut(0)
}
/// Create a SCALAR node and attach it to the document.
///
/// The `style` argument may be ignored by the emitter.
///
/// Returns the node id or 0 on error.
#[must_use]
pub fn add_scalar(&mut self, tag: Option<&str>, value: &str, style: ScalarStyle) -> i32 {
let mark = Mark {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let tag = tag.unwrap_or(DEFAULT_SCALAR_TAG);
let tag_copy = String::from(tag);
let value_copy = String::from(value);
let node = Node {
data: NodeData::Scalar {
value: value_copy,
style,
},
tag: Some(tag_copy),
start_mark: mark,
end_mark: mark,
};
self.nodes.push(node);
self.nodes.len() as i32
}
/// Create a SEQUENCE node and attach it to the document.
///
/// The `style` argument may be ignored by the emitter.
///
/// Returns the node id, which is a nonzero integer.
#[must_use]
pub fn add_sequence(&mut self, tag: Option<&str>, style: SequenceStyle) -> i32 {
let mark = Mark {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let items = Vec::with_capacity(16);
let tag = tag.unwrap_or(DEFAULT_SEQUENCE_TAG);
let tag_copy = String::from(tag);
let node = Node {
data: NodeData::Sequence { items, style },
tag: Some(tag_copy),
start_mark: mark,
end_mark: mark,
};
self.nodes.push(node);
self.nodes.len() as i32
}
/// Create a MAPPING node and attach it to the document.
///
/// The `style` argument may be ignored by the emitter.
///
/// Returns the node id, which is a nonzero integer.
#[must_use]
pub fn add_mapping(&mut self, tag: Option<&str>, style: MappingStyle) -> i32 {
let mark = Mark {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let pairs = Vec::with_capacity(16);
let tag = tag.unwrap_or(DEFAULT_MAPPING_TAG);
let tag_copy = String::from(tag);
let node = Node {
data: NodeData::Mapping { pairs, style },
tag: Some(tag_copy),
start_mark: mark,
end_mark: mark,
};
self.nodes.push(node);
self.nodes.len() as i32
}
/// Add an item to a SEQUENCE node.
pub fn append_sequence_item(&mut self, sequence: i32, item: i32) {
assert!(sequence > 0 && sequence as usize - 1 < self.nodes.len());
assert!(matches!(
&self.nodes[sequence as usize - 1].data,
NodeData::Sequence { .. }
));
assert!(item > 0 && item as usize - 1 < self.nodes.len());
if let NodeData::Sequence { ref mut items, .. } =
&mut self.nodes[sequence as usize - 1].data
{
items.push(item);
}
}
/// Add a pair of a key and a value to a MAPPING node.
pub fn yaml_document_append_mapping_pair(&mut self, mapping: i32, key: i32, value: i32) {
assert!(mapping > 0 && mapping as usize - 1 < self.nodes.len());
assert!(matches!(
&self.nodes[mapping as usize - 1].data,
NodeData::Mapping { .. }
));
assert!(key > 0 && key as usize - 1 < self.nodes.len());
assert!(value > 0 && value as usize - 1 < self.nodes.len());
let pair = NodePair { key, value };
if let NodeData::Mapping { ref mut pairs, .. } = &mut self.nodes[mapping as usize - 1].data
{
pairs.push(pair);
}
}
}

View file

@ -3,10 +3,11 @@ use std::mem::take;
use alloc::string::String;
use alloc::vec;
use crate::yaml::{Anchors, Any, Document, Emitter, Event, EventData, Node, NodeData};
use crate::{
yaml_emitter_emit, EmitterError, DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG,
yaml_emitter_emit, EmitterError, Encoding, DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG,
DEFAULT_SEQUENCE_TAG,
};
use crate::{Anchors, Document, Emitter, Event, EventData, Node, NodeData};
/// Start a YAML stream.
///
@ -15,7 +16,9 @@ use crate::{
pub fn yaml_emitter_open(emitter: &mut Emitter) -> Result<(), EmitterError> {
assert!(!emitter.opened);
let event = Event {
data: EventData::StreamStart { encoding: Any },
data: EventData::StreamStart {
encoding: Encoding::Any,
},
..Default::default()
};
yaml_emitter_emit(emitter, event)?;
@ -45,7 +48,7 @@ pub fn yaml_emitter_close(emitter: &mut Emitter) -> Result<(), EmitterError> {
///
/// The document object may be generated using the
/// [`yaml_parser_load()`](crate::yaml_parser_load) function or the
/// [`yaml_document_new()`](crate::yaml_document_new) function.
/// [`Document::new()`] function.
pub fn yaml_emitter_dump(
emitter: &mut Emitter,
mut document: Document,

View file

@ -1,15 +1,93 @@
use std::collections::VecDeque;
use alloc::string::String;
use crate::api::OUTPUT_BUFFER_SIZE;
use crate::macros::{
is_alpha, is_ascii, is_blank, is_blankz, is_bom, is_break, is_breakz, is_printable, is_space,
};
use crate::yaml::EventData;
use crate::{
yaml_emitter_flush, Break, Emitter, EmitterError, EmitterState, Encoding, Event, MappingStyle,
ScalarStyle, SequenceStyle, TagDirective, VersionDirective, WriterError,
yaml_emitter_flush, Break, EmitterError, Encoding, Event, EventData, MappingStyle, ScalarStyle,
SequenceStyle, TagDirective, VersionDirective, WriterError, OUTPUT_BUFFER_SIZE,
};
/// The emitter structure.
///
/// All members are internal. Manage the structure using the `yaml_emitter_`
/// family of functions.
#[non_exhaustive]
pub struct Emitter<'w> {
/// Write handler.
pub(crate) write_handler: Option<&'w mut dyn std::io::Write>,
/// The working buffer.
///
/// This always contains valid UTF-8.
pub(crate) buffer: String,
/// The raw buffer.
///
/// This contains the output in the encoded format, so for example it may be
/// UTF-16 encoded.
pub(crate) raw_buffer: Vec<u8>,
/// The stream encoding.
pub(crate) encoding: Encoding,
/// If the output is in the canonical style?
pub(crate) canonical: bool,
/// The number of indentation spaces.
pub(crate) best_indent: i32,
/// The preferred width of the output lines.
pub(crate) best_width: i32,
/// Allow unescaped non-ASCII characters?
pub(crate) unicode: bool,
/// The preferred line break.
pub(crate) line_break: Break,
/// The stack of states.
pub(crate) states: Vec<EmitterState>,
/// The current emitter state.
pub(crate) state: EmitterState,
/// The event queue.
pub(crate) events: VecDeque<Event>,
/// The stack of indentation levels.
pub(crate) indents: Vec<i32>,
/// The list of tag directives.
pub(crate) tag_directives: Vec<TagDirective>,
/// The current indentation level.
pub(crate) indent: i32,
/// The current flow level.
pub(crate) flow_level: i32,
/// Is it the document root context?
pub(crate) root_context: bool,
/// Is it a sequence context?
pub(crate) sequence_context: bool,
/// Is it a mapping context?
pub(crate) mapping_context: bool,
/// Is it a simple mapping key context?
pub(crate) simple_key_context: bool,
/// The current line.
pub(crate) line: i32,
/// The current column.
pub(crate) column: i32,
/// If the last character was a whitespace?
pub(crate) whitespace: bool,
/// If the last character was an indentation character (' ', '-', '?', ':')?
pub(crate) indention: bool,
/// If an explicit document end is required?
pub(crate) open_ended: i32,
/// If the stream was already opened?
pub(crate) opened: bool,
/// If the stream was already closed?
pub(crate) closed: bool,
/// The information associated with the document nodes.
// Note: Same length as `document.nodes`.
pub(crate) anchors: Vec<Anchors>,
/// The last assigned anchor id.
pub(crate) last_anchor_id: i32,
}
impl<'a> Default for Emitter<'a> {
fn default() -> Self {
yaml_emitter_new()
}
}
fn FLUSH(emitter: &mut Emitter) -> Result<(), WriterError> {
if emitter.buffer.len() < OUTPUT_BUFFER_SIZE - 5 {
Ok(())
@ -68,6 +146,59 @@ fn WRITE_BREAK_CHAR(emitter: &mut Emitter, ch: char) -> Result<(), WriterError>
Ok(())
}
/// The emitter states.
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum EmitterState {
/// Expect STREAM-START.
#[default]
StreamStart = 0,
/// Expect the first DOCUMENT-START or STREAM-END.
FirstDocumentStart = 1,
/// Expect DOCUMENT-START or STREAM-END.
DocumentStart = 2,
/// Expect the content of a document.
DocumentContent = 3,
/// Expect DOCUMENT-END.
DocumentEnd = 4,
/// Expect the first item of a flow sequence.
FlowSequenceFirstItem = 5,
/// Expect an item of a flow sequence.
FlowSequenceItem = 6,
/// Expect the first key of a flow mapping.
FlowMappingFirstKey = 7,
/// Expect a key of a flow mapping.
FlowMappingKey = 8,
/// Expect a value for a simple key of a flow mapping.
FlowMappingSimpleValue = 9,
/// Expect a value of a flow mapping.
FlowMappingValue = 10,
/// Expect the first item of a block sequence.
BlockSequenceFirstItem = 11,
/// Expect an item of a block sequence.
BlockSequenceItem = 12,
/// Expect the first key of a block mapping.
BlockMappingFirstKey = 13,
/// Expect the key of a block mapping.
BlockMappingKey = 14,
/// Expect a value for a simple key of a block mapping.
BlockMappingSimpleValue = 15,
/// Expect a value of a block mapping.
BlockMappingValue = 16,
/// Expect nothing.
End = 17,
}
#[derive(Copy, Clone, Default)]
pub(crate) struct Anchors {
/// The number of references.
pub references: i32,
/// The anchor id.
pub anchor: i32,
/// If the node has been emitted?
pub serialized: bool,
}
#[derive(Default)]
struct Analysis<'a> {
pub anchor: Option<AnchorAnalysis<'a>>,
@ -109,6 +240,98 @@ fn yaml_emitter_set_emitter_error<T>(
Err(EmitterError::Problem(problem))
}
/// Create an emitter.
pub fn yaml_emitter_new<'w>() -> Emitter<'w> {
Emitter {
write_handler: None,
buffer: String::with_capacity(OUTPUT_BUFFER_SIZE),
raw_buffer: Vec::with_capacity(OUTPUT_BUFFER_SIZE),
encoding: Encoding::Any,
canonical: false,
best_indent: 0,
best_width: 0,
unicode: false,
line_break: Break::default(),
states: Vec::with_capacity(16),
state: EmitterState::default(),
events: VecDeque::with_capacity(16),
indents: Vec::with_capacity(16),
tag_directives: Vec::with_capacity(16),
indent: 0,
flow_level: 0,
root_context: false,
sequence_context: false,
mapping_context: false,
simple_key_context: false,
line: 0,
column: 0,
whitespace: false,
indention: false,
open_ended: 0,
opened: false,
closed: false,
anchors: Vec::new(),
last_anchor_id: 0,
}
}
/// Reset the emitter state.
pub fn yaml_emitter_reset(emitter: &mut Emitter) {
*emitter = yaml_emitter_new();
}
/// Set a string output.
///
/// The emitter will write the output characters to the `output` buffer.
pub fn yaml_emitter_set_output_string<'w>(emitter: &mut Emitter<'w>, output: &'w mut Vec<u8>) {
assert!(emitter.write_handler.is_none());
if emitter.encoding == Encoding::Any {
yaml_emitter_set_encoding(emitter, Encoding::Utf8);
} else if emitter.encoding != Encoding::Utf8 {
panic!("cannot output UTF-16 to String")
}
output.clear();
emitter.write_handler = Some(output);
}
/// Set a generic output handler.
pub fn yaml_emitter_set_output<'w>(emitter: &mut Emitter<'w>, handler: &'w mut dyn std::io::Write) {
assert!(emitter.write_handler.is_none());
emitter.write_handler = Some(handler);
}
/// Set the output encoding.
pub fn yaml_emitter_set_encoding(emitter: &mut Emitter, encoding: Encoding) {
assert_eq!(emitter.encoding, Encoding::Any);
emitter.encoding = encoding;
}
/// Set if the output should be in the "canonical" format as in the YAML
/// specification.
pub fn yaml_emitter_set_canonical(emitter: &mut Emitter, canonical: bool) {
emitter.canonical = canonical;
}
/// Set the indentation increment.
pub fn yaml_emitter_set_indent(emitter: &mut Emitter, indent: i32) {
emitter.best_indent = if 1 < indent && indent < 10 { indent } else { 2 };
}
/// Set the preferred line width. -1 means unlimited.
pub fn yaml_emitter_set_width(emitter: &mut Emitter, width: i32) {
emitter.best_width = if width >= 0 { width } else { -1 };
}
/// Set if unescaped non-ASCII characters are allowed.
pub fn yaml_emitter_set_unicode(emitter: &mut Emitter, unicode: bool) {
emitter.unicode = unicode;
}
/// Set the preferred line break.
pub fn yaml_emitter_set_break(emitter: &mut Emitter, line_break: Break) {
emitter.line_break = line_break;
}
/// Emit an event.
///
/// The event object may be generated using the

269
src/event.rs Normal file
View file

@ -0,0 +1,269 @@
use crate::{
Encoding, MappingStyle, Mark, ScalarStyle, SequenceStyle, TagDirective, VersionDirective,
};
/// The event structure.
#[derive(Default, Debug)]
#[non_exhaustive]
pub struct Event {
/// The event data.
pub data: EventData,
/// The beginning of the event.
pub start_mark: Mark,
/// The end of the event.
pub end_mark: Mark,
}
#[derive(Default, Debug)]
pub enum EventData {
#[default]
NoEvent,
/// The stream parameters (for YAML_STREAM_START_EVENT).
StreamStart {
/// The document encoding.
encoding: Encoding,
},
StreamEnd,
/// The document parameters (for YAML_DOCUMENT_START_EVENT).
DocumentStart {
/// The version directive.
version_directive: Option<VersionDirective>,
/// The tag directives list.
tag_directives: Vec<TagDirective>,
/// Is the document indicator implicit?
implicit: bool,
},
/// The document end parameters (for YAML_DOCUMENT_END_EVENT).
DocumentEnd {
implicit: bool,
},
/// The alias parameters (for YAML_ALIAS_EVENT).
Alias {
/// The anchor.
anchor: String,
},
/// The scalar parameters (for YAML_SCALAR_EVENT).
Scalar {
/// The anchor.
anchor: Option<String>,
/// The tag.
tag: Option<String>,
/// The scalar value.
value: String,
/// Is the tag optional for the plain style?
plain_implicit: bool,
/// Is the tag optional for any non-plain style?
quoted_implicit: bool,
/// The scalar style.
style: ScalarStyle,
},
/// The sequence parameters (for YAML_SEQUENCE_START_EVENT).
SequenceStart {
/// The anchor.
anchor: Option<String>,
/// The tag.
tag: Option<String>,
/// Is the tag optional?
implicit: bool,
/// The sequence style.
style: SequenceStyle,
},
SequenceEnd,
/// The mapping parameters (for YAML_MAPPING_START_EVENT).
MappingStart {
/// The anchor.
anchor: Option<String>,
/// The tag.
tag: Option<String>,
/// Is the tag optional?
implicit: bool,
/// The mapping style.
style: MappingStyle,
},
MappingEnd,
}
impl Event {
/// Create the STREAM-START event.
pub fn stream_start(encoding: Encoding) -> Self {
Event {
data: EventData::StreamStart { encoding },
..Default::default()
}
}
/// Create the STREAM-END event.
pub fn stream_end() -> Self {
Event {
data: EventData::StreamEnd,
..Default::default()
}
}
/// Create the DOCUMENT-START event.
///
/// The `implicit` argument is considered as a stylistic parameter and may be
/// ignored by the emitter.
pub fn document_start(
version_directive: Option<VersionDirective>,
tag_directives_in: &[TagDirective],
implicit: bool,
) -> Self {
let tag_directives = tag_directives_in.to_vec();
Event {
data: EventData::DocumentStart {
version_directive,
tag_directives,
implicit,
},
..Default::default()
}
}
/// Create the DOCUMENT-END event.
///
/// The `implicit` argument is considered as a stylistic parameter and may be
/// ignored by the emitter.
pub fn document_end(implicit: bool) -> Self {
Event {
data: EventData::DocumentEnd { implicit },
..Default::default()
}
}
/// Create an ALIAS event.
pub fn alias(anchor: &str) -> Self {
Event {
data: EventData::Alias {
anchor: String::from(anchor),
},
..Default::default()
}
}
/// Create a SCALAR event.
///
/// The `style` argument may be ignored by the emitter.
///
/// Either the `tag` attribute or one of the `plain_implicit` and
/// `quoted_implicit` flags must be set.
///
pub fn scalar(
anchor: Option<&str>,
tag: Option<&str>,
value: &str,
plain_implicit: bool,
quoted_implicit: bool,
style: ScalarStyle,
) -> Self {
let mark = Mark {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let mut anchor_copy: Option<String> = None;
let mut tag_copy: Option<String> = None;
if let Some(anchor) = anchor {
anchor_copy = Some(String::from(anchor));
}
if let Some(tag) = tag {
tag_copy = Some(String::from(tag));
}
Event {
data: EventData::Scalar {
anchor: anchor_copy,
tag: tag_copy,
value: String::from(value),
plain_implicit,
quoted_implicit,
style,
},
start_mark: mark,
end_mark: mark,
}
}
/// Create a SEQUENCE-START event.
///
/// The `style` argument may be ignored by the emitter.
///
/// Either the `tag` attribute or the `implicit` flag must be set.
pub fn sequence_start(
anchor: Option<&str>,
tag: Option<&str>,
implicit: bool,
style: SequenceStyle,
) -> Self {
let mut anchor_copy: Option<String> = None;
let mut tag_copy: Option<String> = None;
if let Some(anchor) = anchor {
anchor_copy = Some(String::from(anchor));
}
if let Some(tag) = tag {
tag_copy = Some(String::from(tag));
}
Event {
data: EventData::SequenceStart {
anchor: anchor_copy,
tag: tag_copy,
implicit,
style,
},
..Default::default()
}
}
/// Create a SEQUENCE-END event.
pub fn sequence_end() -> Self {
Event {
data: EventData::SequenceEnd,
..Default::default()
}
}
/// Create a MAPPING-START event.
///
/// The `style` argument may be ignored by the emitter.
///
/// Either the `tag` attribute or the `implicit` flag must be set.
pub fn mapping_start(
anchor: Option<&str>,
tag: Option<&str>,
implicit: bool,
style: MappingStyle,
) -> Self {
let mut anchor_copy: Option<String> = None;
let mut tag_copy: Option<String> = None;
if let Some(anchor) = anchor {
anchor_copy = Some(String::from(anchor));
}
if let Some(tag) = tag {
tag_copy = Some(String::from(tag));
}
Event {
data: EventData::MappingStart {
anchor: anchor_copy,
tag: tag_copy,
implicit,
style,
},
..Default::default()
}
}
/// Create a MAPPING-END event.
pub fn mapping_end() -> Self {
Event {
data: EventData::MappingEnd,
..Default::default()
}
}
}

View file

@ -27,47 +27,150 @@ extern crate alloc;
#[macro_use]
mod macros;
mod api;
mod document;
mod dumper;
mod emitter;
mod error;
mod event;
mod loader;
mod parser;
mod reader;
mod scanner;
mod token;
mod writer;
mod yaml;
pub use crate::api::{
yaml_alias_event_new, yaml_document_add_mapping, yaml_document_add_scalar,
yaml_document_add_sequence, yaml_document_append_mapping_pair,
yaml_document_append_sequence_item, yaml_document_delete, yaml_document_end_event_new,
yaml_document_get_node, yaml_document_get_root_node, yaml_document_new,
yaml_document_start_event_new, yaml_emitter_new, yaml_emitter_reset, yaml_emitter_set_break,
yaml_emitter_set_canonical, yaml_emitter_set_encoding, yaml_emitter_set_indent,
yaml_emitter_set_output, yaml_emitter_set_output_string, yaml_emitter_set_unicode,
yaml_emitter_set_width, yaml_mapping_end_event_new, yaml_mapping_start_event_new,
yaml_parser_new, yaml_parser_reset, yaml_parser_set_encoding, yaml_parser_set_input,
yaml_parser_set_input_string, yaml_scalar_event_new, yaml_sequence_end_event_new,
yaml_sequence_start_event_new, yaml_stream_end_event_new, yaml_stream_start_event_new,
};
pub use crate::document::*;
pub use crate::dumper::{yaml_emitter_close, yaml_emitter_dump, yaml_emitter_open};
pub use crate::emitter::yaml_emitter_emit;
pub use crate::emitter::*;
pub use crate::error::*;
pub use crate::event::*;
pub use crate::loader::yaml_parser_load;
pub use crate::parser::yaml_parser_parse;
pub use crate::parser::*;
pub use crate::scanner::yaml_parser_scan;
pub use crate::token::*;
pub use crate::writer::yaml_emitter_flush;
pub use crate::yaml::{
AliasData, Break, Document, Emitter, EmitterState, Encoding, Event, EventData, MappingStyle,
Node, NodeItem, NodePair, Parser, ParserState, ScalarStyle, SequenceStyle, SimpleKey,
TagDirective, Token, TokenData, VersionDirective,
};
#[doc(hidden)]
pub use crate::yaml::{
BOOL_TAG, DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG, FLOAT_TAG, INT_TAG,
MAP_TAG, NULL_TAG, SEQ_TAG, STR_TAG, TIMESTAMP_TAG,
};
pub(crate) const INPUT_RAW_BUFFER_SIZE: usize = 16384;
pub(crate) const INPUT_BUFFER_SIZE: usize = INPUT_RAW_BUFFER_SIZE;
pub(crate) const OUTPUT_BUFFER_SIZE: usize = 16384;
/// The tag `!!null` with the only possible value: `null`.
pub const NULL_TAG: &str = "tag:yaml.org,2002:null";
/// The tag `!!bool` with the values: `true` and `false`.
pub const BOOL_TAG: &str = "tag:yaml.org,2002:bool";
/// The tag `!!str` for string values.
pub const STR_TAG: &str = "tag:yaml.org,2002:str";
/// The tag `!!int` for integer values.
pub const INT_TAG: &str = "tag:yaml.org,2002:int";
/// The tag `!!float` for float values.
pub const FLOAT_TAG: &str = "tag:yaml.org,2002:float";
/// The tag `!!timestamp` for date and time values.
pub const TIMESTAMP_TAG: &str = "tag:yaml.org,2002:timestamp";
/// The tag `!!seq` is used to denote sequences.
pub const SEQ_TAG: &str = "tag:yaml.org,2002:seq";
/// The tag `!!map` is used to denote mapping.
pub const MAP_TAG: &str = "tag:yaml.org,2002:map";
/// The default scalar tag is `!!str`.
pub const DEFAULT_SCALAR_TAG: &str = STR_TAG;
/// The default sequence tag is `!!seq`.
pub const DEFAULT_SEQUENCE_TAG: &str = SEQ_TAG;
/// The default mapping tag is `!!map`.
pub const DEFAULT_MAPPING_TAG: &str = MAP_TAG;
/// The version directive data.
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
pub struct VersionDirective {
/// The major version number.
pub major: i32,
/// The minor version number.
pub minor: i32,
}
/// The tag directive data.
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct TagDirective {
/// The tag handle.
pub handle: String,
/// The tag prefix.
pub prefix: String,
}
/// The stream encoding.
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum Encoding {
/// Let the parser choose the encoding.
#[default]
Any = 0,
/// The default UTF-8 encoding.
Utf8 = 1,
/// The UTF-16-LE encoding with BOM.
Utf16Le = 2,
/// The UTF-16-BE encoding with BOM.
Utf16Be = 3,
}
/// Line break type.
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum Break {
/// Let the parser choose the break type.
#[default]
Any = 0,
/// Use CR for line breaks (Mac style).
Cr = 1,
/// Use LN for line breaks (Unix style).
Ln = 2,
/// Use CR LN for line breaks (DOS style).
CrLn = 3,
}
/// Scalar styles.
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum ScalarStyle {
/// Let the emitter choose the style.
#[default]
Any = 0,
/// The plain scalar style.
Plain = 1,
/// The single-quoted scalar style.
SingleQuoted = 2,
/// The double-quoted scalar style.
DoubleQuoted = 3,
/// The literal scalar style.
Literal = 4,
/// The folded scalar style.
Folded = 5,
}
/// Sequence styles.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum SequenceStyle {
/// Let the emitter choose the style.
Any = 0,
/// The block sequence style.
Block = 1,
/// The flow sequence style.
Flow = 2,
}
/// Mapping styles.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum MappingStyle {
/// Let the emitter choose the style.
Any = 0,
/// The block mapping style.
Block = 1,
/// The flow mapping style.
Flow = 2,
}
#[cfg(test)]
mod tests {
@ -186,11 +289,11 @@ foo: bar
let mut output = Vec::new();
yaml_emitter_set_output_string(&mut emitter, &mut output);
let event = yaml_stream_start_event_new(Encoding::Utf8);
let event = Event::stream_start(Encoding::Utf8);
yaml_emitter_emit(&mut emitter, event).unwrap();
let event = yaml_document_start_event_new(None, &[], true);
let event = Event::document_start(None, &[], true);
yaml_emitter_emit(&mut emitter, event).unwrap();
let event = yaml_scalar_event_new(
let event = Event::scalar(
None,
None,
"1st non-empty\n2nd non-empty 3rd non-empty",
@ -199,9 +302,9 @@ foo: bar
ScalarStyle::Plain,
);
yaml_emitter_emit(&mut emitter, event).unwrap();
let event = yaml_document_end_event_new(true);
let event = Event::document_end(true);
yaml_emitter_emit(&mut emitter, event).unwrap();
let event = yaml_stream_end_event_new();
let event = Event::stream_end();
yaml_emitter_emit(&mut emitter, event).unwrap();
assert_eq!(

View file

@ -1,9 +1,8 @@
use alloc::string::String;
use alloc::{vec, vec::Vec};
use crate::yaml::{EventData, NodeData};
use crate::{
yaml_document_new, yaml_parser_parse, AliasData, ComposerError, Document, Event, Mark, Node,
yaml_parser_parse, AliasData, ComposerError, Document, Event, EventData, Mark, Node, NodeData,
NodePair, Parser, DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG,
};
@ -21,7 +20,7 @@ use crate::{
/// [`yaml_parser_parse()`](crate::yaml_parser_parse). Doing this will break the
/// parser.
pub fn yaml_parser_load(parser: &mut Parser) -> Result<Document, ComposerError> {
let mut document = yaml_document_new(None, &[], false, false);
let mut document = Document::new(None, &[], false, false);
document.nodes.reserve(16);
if !parser.stream_start_produced {

View file

@ -1,13 +1,154 @@
use std::collections::VecDeque;
use alloc::string::String;
use alloc::{vec, vec::Vec};
use crate::scanner::yaml_parser_fetch_more_tokens;
use crate::yaml::{EventData, TokenData};
use crate::{
Event, MappingStyle, Mark, Parser, ParserError, ParserState, ScalarStyle, SequenceStyle,
TagDirective, Token, VersionDirective,
Encoding, Event, EventData, MappingStyle, Mark, ParserError, ScalarStyle, SequenceStyle,
TagDirective, Token, TokenData, VersionDirective, INPUT_BUFFER_SIZE,
};
/// The parser structure.
///
/// All members are internal. Manage the structure using the `yaml_parser_`
/// family of functions.
#[non_exhaustive]
pub struct Parser<'r> {
/// Read handler.
pub(crate) read_handler: Option<&'r mut dyn std::io::BufRead>,
/// EOF flag
pub(crate) eof: bool,
/// The working buffer.
///
/// This always contains valid UTF-8.
pub(crate) buffer: VecDeque<char>,
/// The number of unread characters in the buffer.
pub(crate) unread: usize,
/// The input encoding.
pub(crate) encoding: Encoding,
/// The offset of the current position (in bytes).
pub(crate) offset: usize,
/// The mark of the current position.
pub(crate) mark: Mark,
/// Have we started to scan the input stream?
pub(crate) stream_start_produced: bool,
/// Have we reached the end of the input stream?
pub(crate) stream_end_produced: bool,
/// The number of unclosed '[' and '{' indicators.
pub(crate) flow_level: i32,
/// The tokens queue.
pub(crate) tokens: VecDeque<Token>,
/// The number of tokens fetched from the queue.
pub(crate) tokens_parsed: usize,
/// Does the tokens queue contain a token ready for dequeueing.
pub(crate) token_available: bool,
/// The indentation levels stack.
pub(crate) indents: Vec<i32>,
/// The current indentation level.
pub(crate) indent: i32,
/// May a simple key occur at the current position?
pub(crate) simple_key_allowed: bool,
/// The stack of simple keys.
pub(crate) simple_keys: Vec<SimpleKey>,
/// The parser states stack.
pub(crate) states: Vec<ParserState>,
/// The current parser state.
pub(crate) state: ParserState,
/// The stack of marks.
pub(crate) marks: Vec<Mark>,
/// The list of TAG directives.
pub(crate) tag_directives: Vec<TagDirective>,
/// The alias data.
pub(crate) aliases: Vec<AliasData>,
}
impl<'r> Default for Parser<'r> {
fn default() -> Self {
yaml_parser_new()
}
}
/// This structure holds information about a potential simple key.
#[derive(Copy, Clone)]
#[non_exhaustive]
pub struct SimpleKey {
/// Is a simple key possible?
pub possible: bool,
/// Is a simple key required?
pub required: bool,
/// The number of the token.
pub token_number: usize,
/// The position mark.
pub mark: Mark,
}
/// The states of the parser.
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum ParserState {
/// Expect STREAM-START.
#[default]
StreamStart = 0,
/// Expect the beginning of an implicit document.
ImplicitDocumentStart = 1,
/// Expect DOCUMENT-START.
DocumentStart = 2,
/// Expect the content of a document.
DocumentContent = 3,
/// Expect DOCUMENT-END.
DocumentEnd = 4,
/// Expect a block node.
BlockNode = 5,
/// Expect a block node or indentless sequence.
BlockNodeOrIndentlessSequence = 6,
/// Expect a flow node.
FlowNode = 7,
/// Expect the first entry of a block sequence.
BlockSequenceFirstEntry = 8,
/// Expect an entry of a block sequence.
BlockSequenceEntry = 9,
/// Expect an entry of an indentless sequence.
IndentlessSequenceEntry = 10,
/// Expect the first key of a block mapping.
BlockMappingFirstKey = 11,
/// Expect a block mapping key.
BlockMappingKey = 12,
/// Expect a block mapping value.
BlockMappingValue = 13,
/// Expect the first entry of a flow sequence.
FlowSequenceFirstEntry = 14,
/// Expect an entry of a flow sequence.
FlowSequenceEntry = 15,
/// Expect a key of an ordered mapping.
FlowSequenceEntryMappingKey = 16,
/// Expect a value of an ordered mapping.
FlowSequenceEntryMappingValue = 17,
/// Expect the and of an ordered mapping entry.
FlowSequenceEntryMappingEnd = 18,
/// Expect the first key of a flow mapping.
FlowMappingFirstKey = 19,
/// Expect a key of a flow mapping.
FlowMappingKey = 20,
/// Expect a value of a flow mapping.
FlowMappingValue = 21,
/// Expect an empty value of a flow mapping.
FlowMappingEmptyValue = 22,
/// Expect nothing.
End = 23,
}
/// This structure holds aliases data.
#[non_exhaustive]
pub struct AliasData {
/// The anchor.
pub anchor: String,
/// The node id.
pub index: i32,
/// The anchor mark.
pub mark: Mark,
}
fn PEEK_TOKEN<'a>(parser: &'a mut Parser) -> Result<&'a Token, ParserError> {
if parser.token_available {
return Ok(parser
@ -55,6 +196,57 @@ fn SKIP_TOKEN(parser: &mut Parser) {
);
}
/// Create a parser.
pub fn yaml_parser_new<'r>() -> Parser<'r> {
Parser {
read_handler: None,
eof: false,
buffer: VecDeque::with_capacity(INPUT_BUFFER_SIZE),
unread: 0,
encoding: Encoding::Any,
offset: 0,
mark: Mark::default(),
stream_start_produced: false,
stream_end_produced: false,
flow_level: 0,
tokens: VecDeque::with_capacity(16),
tokens_parsed: 0,
token_available: false,
indents: Vec::with_capacity(16),
indent: 0,
simple_key_allowed: false,
simple_keys: Vec::with_capacity(16),
states: Vec::with_capacity(16),
state: ParserState::default(),
marks: Vec::with_capacity(16),
tag_directives: Vec::with_capacity(16),
aliases: Vec::new(),
}
}
/// Reset the parser state.
pub fn yaml_parser_reset(parser: &mut Parser) {
*parser = yaml_parser_new();
}
/// Set a string input.
pub fn yaml_parser_set_input_string<'r>(parser: &mut Parser<'r>, input: &'r mut &[u8]) {
assert!((parser.read_handler).is_none());
parser.read_handler = Some(input);
}
/// Set a generic input handler.
pub fn yaml_parser_set_input<'r>(parser: &mut Parser<'r>, input: &'r mut dyn std::io::BufRead) {
assert!((parser.read_handler).is_none());
parser.read_handler = Some(input);
}
/// Set the source encoding.
pub fn yaml_parser_set_encoding(parser: &mut Parser, encoding: Encoding) {
assert!(parser.encoding == Encoding::Any);
parser.encoding = encoding;
}
/// Parse the input stream and produce the next parsing event.
///
/// Call the function subsequently to produce a sequence of events corresponding

View file

@ -2,8 +2,7 @@ use alloc::string::String;
use crate::macros::{is_blankz, is_break, vecdeque_starts_with};
use crate::reader::yaml_parser_update_buffer;
use crate::yaml::TokenData;
use crate::{Mark, Parser, ReaderError, ScalarStyle, ScannerError, SimpleKey, Token};
use crate::{Mark, Parser, ReaderError, ScalarStyle, ScannerError, SimpleKey, Token, TokenData};
fn CACHE(parser: &mut Parser, length: usize) -> Result<(), ReaderError> {
if parser.unread >= length {

91
src/token.rs Normal file
View file

@ -0,0 +1,91 @@
use crate::{Encoding, Mark, ScalarStyle};
/// The token structure.
#[derive(Default)]
#[non_exhaustive]
pub struct Token {
/// The token type.
pub data: TokenData,
/// The beginning of the token.
pub start_mark: Mark,
/// The end of the token.
pub end_mark: Mark,
}
#[derive(Default)]
pub enum TokenData {
/// An empty token.
#[default]
NoToken,
/// A STREAM-START token.
StreamStart {
/// The stream encoding.
encoding: Encoding,
},
/// A STREAM-END token.
StreamEnd,
/// A VERSION-DIRECTIVE token.
VersionDirective {
/// The major version number.
major: i32,
/// The minor version number.
minor: i32,
},
/// A TAG-DIRECTIVE token.
TagDirective {
/// The tag handle.
handle: String,
/// The tag prefix.
prefix: String,
},
/// A DOCUMENT-START token.
DocumentStart,
/// A DOCUMENT-END token.
DocumentEnd,
/// A BLOCK-SEQUENCE-START token.
BlockSequenceStart,
/// A BLOCK-MAPPING-START token.
BlockMappingStart,
/// A BLOCK-END token.
BlockEnd,
/// A FLOW-SEQUENCE-START token.
FlowSequenceStart,
/// A FLOW-SEQUENCE-END token.
FlowSequenceEnd,
/// A FLOW-MAPPING-START token.
FlowMappingStart,
/// A FLOW-MAPPING-END token.
FlowMappingEnd,
/// A BLOCK-ENTRY token.
BlockEntry,
/// A FLOW-ENTRY token.
FlowEntry,
/// A KEY token.
Key,
/// A VALUE token.
Value,
/// An ALIAS token.
Alias {
/// The alias value.
value: String,
},
/// An ANCHOR token.
Anchor {
/// The anchor value.
value: String,
},
/// A TAG token.
Tag {
/// The tag handle.
handle: String,
/// The tag suffix.
suffix: String,
},
/// A SCALAR token.
Scalar {
/// The scalar value.
value: String,
/// The scalar style.
style: ScalarStyle,
},
}

View file

@ -1,654 +0,0 @@
use alloc::collections::VecDeque;
use alloc::string::String;
use alloc::vec::Vec;
use crate::{api::yaml_parser_new, yaml_emitter_new, Mark};
pub use self::Encoding::*;
/// The tag `!!null` with the only possible value: `null`.
pub const NULL_TAG: &str = "tag:yaml.org,2002:null";
/// The tag `!!bool` with the values: `true` and `false`.
pub const BOOL_TAG: &str = "tag:yaml.org,2002:bool";
/// The tag `!!str` for string values.
pub const STR_TAG: &str = "tag:yaml.org,2002:str";
/// The tag `!!int` for integer values.
pub const INT_TAG: &str = "tag:yaml.org,2002:int";
/// The tag `!!float` for float values.
pub const FLOAT_TAG: &str = "tag:yaml.org,2002:float";
/// The tag `!!timestamp` for date and time values.
pub const TIMESTAMP_TAG: &str = "tag:yaml.org,2002:timestamp";
/// The tag `!!seq` is used to denote sequences.
pub const SEQ_TAG: &str = "tag:yaml.org,2002:seq";
/// The tag `!!map` is used to denote mapping.
pub const MAP_TAG: &str = "tag:yaml.org,2002:map";
/// The default scalar tag is `!!str`.
pub const DEFAULT_SCALAR_TAG: &str = STR_TAG;
/// The default sequence tag is `!!seq`.
pub const DEFAULT_SEQUENCE_TAG: &str = SEQ_TAG;
/// The default mapping tag is `!!map`.
pub const DEFAULT_MAPPING_TAG: &str = MAP_TAG;
/// The version directive data.
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
pub struct VersionDirective {
/// The major version number.
pub major: i32,
/// The minor version number.
pub minor: i32,
}
/// The tag directive data.
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct TagDirective {
/// The tag handle.
pub handle: String,
/// The tag prefix.
pub prefix: String,
}
/// The stream encoding.
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum Encoding {
/// Let the parser choose the encoding.
#[default]
Any = 0,
/// The default UTF-8 encoding.
Utf8 = 1,
/// The UTF-16-LE encoding with BOM.
Utf16Le = 2,
/// The UTF-16-BE encoding with BOM.
Utf16Be = 3,
}
/// Line break type.
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum Break {
/// Let the parser choose the break type.
#[default]
Any = 0,
/// Use CR for line breaks (Mac style).
Cr = 1,
/// Use LN for line breaks (Unix style).
Ln = 2,
/// Use CR LN for line breaks (DOS style).
CrLn = 3,
}
/// Scalar styles.
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum ScalarStyle {
/// Let the emitter choose the style.
#[default]
Any = 0,
/// The plain scalar style.
Plain = 1,
/// The single-quoted scalar style.
SingleQuoted = 2,
/// The double-quoted scalar style.
DoubleQuoted = 3,
/// The literal scalar style.
Literal = 4,
/// The folded scalar style.
Folded = 5,
}
/// Sequence styles.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum SequenceStyle {
/// Let the emitter choose the style.
Any = 0,
/// The block sequence style.
Block = 1,
/// The flow sequence style.
Flow = 2,
}
/// Mapping styles.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum MappingStyle {
/// Let the emitter choose the style.
Any = 0,
/// The block mapping style.
Block = 1,
/// The flow mapping style.
Flow = 2,
}
/// The token structure.
#[derive(Default)]
#[non_exhaustive]
pub struct Token {
/// The token type.
pub data: TokenData,
/// The beginning of the token.
pub start_mark: Mark,
/// The end of the token.
pub end_mark: Mark,
}
#[derive(Default)]
pub enum TokenData {
/// An empty token.
#[default]
NoToken,
/// A STREAM-START token.
StreamStart {
/// The stream encoding.
encoding: Encoding,
},
/// A STREAM-END token.
StreamEnd,
/// A VERSION-DIRECTIVE token.
VersionDirective {
/// The major version number.
major: i32,
/// The minor version number.
minor: i32,
},
/// A TAG-DIRECTIVE token.
TagDirective {
/// The tag handle.
handle: String,
/// The tag prefix.
prefix: String,
},
/// A DOCUMENT-START token.
DocumentStart,
/// A DOCUMENT-END token.
DocumentEnd,
/// A BLOCK-SEQUENCE-START token.
BlockSequenceStart,
/// A BLOCK-MAPPING-START token.
BlockMappingStart,
/// A BLOCK-END token.
BlockEnd,
/// A FLOW-SEQUENCE-START token.
FlowSequenceStart,
/// A FLOW-SEQUENCE-END token.
FlowSequenceEnd,
/// A FLOW-MAPPING-START token.
FlowMappingStart,
/// A FLOW-MAPPING-END token.
FlowMappingEnd,
/// A BLOCK-ENTRY token.
BlockEntry,
/// A FLOW-ENTRY token.
FlowEntry,
/// A KEY token.
Key,
/// A VALUE token.
Value,
/// An ALIAS token.
Alias {
/// The alias value.
value: String,
},
/// An ANCHOR token.
Anchor {
/// The anchor value.
value: String,
},
/// A TAG token.
Tag {
/// The tag handle.
handle: String,
/// The tag suffix.
suffix: String,
},
/// A SCALAR token.
Scalar {
/// The scalar value.
value: String,
/// The scalar style.
style: ScalarStyle,
},
}
/// The event structure.
#[derive(Default, Debug)]
#[non_exhaustive]
pub struct Event {
/// The event data.
pub data: EventData,
/// The beginning of the event.
pub start_mark: Mark,
/// The end of the event.
pub end_mark: Mark,
}
#[derive(Default, Debug)]
pub enum EventData {
#[default]
NoEvent,
/// The stream parameters (for YAML_STREAM_START_EVENT).
StreamStart {
/// The document encoding.
encoding: Encoding,
},
StreamEnd,
/// The document parameters (for YAML_DOCUMENT_START_EVENT).
DocumentStart {
/// The version directive.
version_directive: Option<VersionDirective>,
/// The tag directives list.
tag_directives: Vec<TagDirective>,
/// Is the document indicator implicit?
implicit: bool,
},
/// The document end parameters (for YAML_DOCUMENT_END_EVENT).
DocumentEnd {
implicit: bool,
},
/// The alias parameters (for YAML_ALIAS_EVENT).
Alias {
/// The anchor.
anchor: String,
},
/// The scalar parameters (for YAML_SCALAR_EVENT).
Scalar {
/// The anchor.
anchor: Option<String>,
/// The tag.
tag: Option<String>,
/// The scalar value.
value: String,
/// Is the tag optional for the plain style?
plain_implicit: bool,
/// Is the tag optional for any non-plain style?
quoted_implicit: bool,
/// The scalar style.
style: ScalarStyle,
},
/// The sequence parameters (for YAML_SEQUENCE_START_EVENT).
SequenceStart {
/// The anchor.
anchor: Option<String>,
/// The tag.
tag: Option<String>,
/// Is the tag optional?
implicit: bool,
/// The sequence style.
style: SequenceStyle,
},
SequenceEnd,
/// The mapping parameters (for YAML_MAPPING_START_EVENT).
MappingStart {
/// The anchor.
anchor: Option<String>,
/// The tag.
tag: Option<String>,
/// Is the tag optional?
implicit: bool,
/// The mapping style.
style: MappingStyle,
},
MappingEnd,
}
/// The node structure.
#[derive(Clone, Default, Debug)]
#[non_exhaustive]
pub struct Node {
/// The node type.
pub data: NodeData,
/// The node tag.
pub tag: Option<String>,
/// The beginning of the node.
pub start_mark: Mark,
/// The end of the node.
pub end_mark: Mark,
}
/// Node types.
#[derive(Clone, Default, Debug)]
pub enum NodeData {
/// An empty node.
#[default]
NoNode,
/// A scalar node.
Scalar {
/// The scalar value.
value: String,
/// The scalar style.
style: ScalarStyle,
},
/// A sequence node.
Sequence {
/// The stack of sequence items.
items: Vec<NodeItem>,
/// The sequence style.
style: SequenceStyle,
},
/// A mapping node.
Mapping {
/// The stack of mapping pairs (key, value).
pairs: Vec<NodePair>,
/// The mapping style.
style: MappingStyle,
},
}
/// An element of a sequence node.
pub type NodeItem = i32;
/// An element of a mapping node.
#[derive(Copy, Clone, Default, Debug)]
#[non_exhaustive]
pub struct NodePair {
/// The key of the element.
pub key: i32,
/// The value of the element.
pub value: i32,
}
/// The document structure.
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Document {
/// The document nodes.
pub nodes: Vec<Node>,
/// The version directive.
pub version_directive: Option<VersionDirective>,
/// The list of tag directives.
///
/// ```
/// # const _: &str = stringify! {
/// struct {
/// /// The beginning of the tag directives list.
/// start: *mut yaml_tag_directive_t,
/// /// The end of the tag directives list.
/// end: *mut yaml_tag_directive_t,
/// }
/// # };
/// ```
pub tag_directives: Vec<TagDirective>,
/// Is the document start indicator implicit?
pub start_implicit: bool,
/// Is the document end indicator implicit?
pub end_implicit: bool,
/// The beginning of the document.
pub start_mark: Mark,
/// The end of the document.
pub end_mark: Mark,
}
/// This structure holds information about a potential simple key.
#[derive(Copy, Clone)]
#[non_exhaustive]
pub struct SimpleKey {
/// Is a simple key possible?
pub possible: bool,
/// Is a simple key required?
pub required: bool,
/// The number of the token.
pub token_number: usize,
/// The position mark.
pub mark: Mark,
}
/// The states of the parser.
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum ParserState {
/// Expect STREAM-START.
#[default]
StreamStart = 0,
/// Expect the beginning of an implicit document.
ImplicitDocumentStart = 1,
/// Expect DOCUMENT-START.
DocumentStart = 2,
/// Expect the content of a document.
DocumentContent = 3,
/// Expect DOCUMENT-END.
DocumentEnd = 4,
/// Expect a block node.
BlockNode = 5,
/// Expect a block node or indentless sequence.
BlockNodeOrIndentlessSequence = 6,
/// Expect a flow node.
FlowNode = 7,
/// Expect the first entry of a block sequence.
BlockSequenceFirstEntry = 8,
/// Expect an entry of a block sequence.
BlockSequenceEntry = 9,
/// Expect an entry of an indentless sequence.
IndentlessSequenceEntry = 10,
/// Expect the first key of a block mapping.
BlockMappingFirstKey = 11,
/// Expect a block mapping key.
BlockMappingKey = 12,
/// Expect a block mapping value.
BlockMappingValue = 13,
/// Expect the first entry of a flow sequence.
FlowSequenceFirstEntry = 14,
/// Expect an entry of a flow sequence.
FlowSequenceEntry = 15,
/// Expect a key of an ordered mapping.
FlowSequenceEntryMappingKey = 16,
/// Expect a value of an ordered mapping.
FlowSequenceEntryMappingValue = 17,
/// Expect the and of an ordered mapping entry.
FlowSequenceEntryMappingEnd = 18,
/// Expect the first key of a flow mapping.
FlowMappingFirstKey = 19,
/// Expect a key of a flow mapping.
FlowMappingKey = 20,
/// Expect a value of a flow mapping.
FlowMappingValue = 21,
/// Expect an empty value of a flow mapping.
FlowMappingEmptyValue = 22,
/// Expect nothing.
End = 23,
}
/// This structure holds aliases data.
#[non_exhaustive]
pub struct AliasData {
/// The anchor.
pub anchor: String,
/// The node id.
pub index: i32,
/// The anchor mark.
pub mark: Mark,
}
/// The parser structure.
///
/// All members are internal. Manage the structure using the `yaml_parser_`
/// family of functions.
#[non_exhaustive]
pub struct Parser<'r> {
/// Read handler.
pub(crate) read_handler: Option<&'r mut dyn std::io::BufRead>,
/// EOF flag
pub(crate) eof: bool,
/// The working buffer.
///
/// This always contains valid UTF-8.
pub(crate) buffer: VecDeque<char>,
/// The number of unread characters in the buffer.
pub(crate) unread: usize,
/// The input encoding.
pub(crate) encoding: Encoding,
/// The offset of the current position (in bytes).
pub(crate) offset: usize,
/// The mark of the current position.
pub(crate) mark: Mark,
/// Have we started to scan the input stream?
pub(crate) stream_start_produced: bool,
/// Have we reached the end of the input stream?
pub(crate) stream_end_produced: bool,
/// The number of unclosed '[' and '{' indicators.
pub(crate) flow_level: i32,
/// The tokens queue.
pub(crate) tokens: VecDeque<Token>,
/// The number of tokens fetched from the queue.
pub(crate) tokens_parsed: usize,
/// Does the tokens queue contain a token ready for dequeueing.
pub(crate) token_available: bool,
/// The indentation levels stack.
pub(crate) indents: Vec<i32>,
/// The current indentation level.
pub(crate) indent: i32,
/// May a simple key occur at the current position?
pub(crate) simple_key_allowed: bool,
/// The stack of simple keys.
pub(crate) simple_keys: Vec<SimpleKey>,
/// The parser states stack.
pub(crate) states: Vec<ParserState>,
/// The current parser state.
pub(crate) state: ParserState,
/// The stack of marks.
pub(crate) marks: Vec<Mark>,
/// The list of TAG directives.
pub(crate) tag_directives: Vec<TagDirective>,
/// The alias data.
pub(crate) aliases: Vec<AliasData>,
}
impl<'r> Default for Parser<'r> {
fn default() -> Self {
yaml_parser_new()
}
}
/// The emitter states.
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum EmitterState {
/// Expect STREAM-START.
#[default]
StreamStart = 0,
/// Expect the first DOCUMENT-START or STREAM-END.
FirstDocumentStart = 1,
/// Expect DOCUMENT-START or STREAM-END.
DocumentStart = 2,
/// Expect the content of a document.
DocumentContent = 3,
/// Expect DOCUMENT-END.
DocumentEnd = 4,
/// Expect the first item of a flow sequence.
FlowSequenceFirstItem = 5,
/// Expect an item of a flow sequence.
FlowSequenceItem = 6,
/// Expect the first key of a flow mapping.
FlowMappingFirstKey = 7,
/// Expect a key of a flow mapping.
FlowMappingKey = 8,
/// Expect a value for a simple key of a flow mapping.
FlowMappingSimpleValue = 9,
/// Expect a value of a flow mapping.
FlowMappingValue = 10,
/// Expect the first item of a block sequence.
BlockSequenceFirstItem = 11,
/// Expect an item of a block sequence.
BlockSequenceItem = 12,
/// Expect the first key of a block mapping.
BlockMappingFirstKey = 13,
/// Expect the key of a block mapping.
BlockMappingKey = 14,
/// Expect a value for a simple key of a block mapping.
BlockMappingSimpleValue = 15,
/// Expect a value of a block mapping.
BlockMappingValue = 16,
/// Expect nothing.
End = 17,
}
#[derive(Copy, Clone, Default)]
pub(crate) struct Anchors {
/// The number of references.
pub references: i32,
/// The anchor id.
pub anchor: i32,
/// If the node has been emitted?
pub serialized: bool,
}
/// The emitter structure.
///
/// All members are internal. Manage the structure using the `yaml_emitter_`
/// family of functions.
#[non_exhaustive]
pub struct Emitter<'w> {
/// Write handler.
pub(crate) write_handler: Option<&'w mut dyn std::io::Write>,
/// The working buffer.
///
/// This always contains valid UTF-8.
pub(crate) buffer: String,
/// The raw buffer.
///
/// This contains the output in the encoded format, so for example it may be
/// UTF-16 encoded.
pub(crate) raw_buffer: Vec<u8>,
/// The stream encoding.
pub(crate) encoding: Encoding,
/// If the output is in the canonical style?
pub(crate) canonical: bool,
/// The number of indentation spaces.
pub(crate) best_indent: i32,
/// The preferred width of the output lines.
pub(crate) best_width: i32,
/// Allow unescaped non-ASCII characters?
pub(crate) unicode: bool,
/// The preferred line break.
pub(crate) line_break: Break,
/// The stack of states.
pub(crate) states: Vec<EmitterState>,
/// The current emitter state.
pub(crate) state: EmitterState,
/// The event queue.
pub(crate) events: VecDeque<Event>,
/// The stack of indentation levels.
pub(crate) indents: Vec<i32>,
/// The list of tag directives.
pub(crate) tag_directives: Vec<TagDirective>,
/// The current indentation level.
pub(crate) indent: i32,
/// The current flow level.
pub(crate) flow_level: i32,
/// Is it the document root context?
pub(crate) root_context: bool,
/// Is it a sequence context?
pub(crate) sequence_context: bool,
/// Is it a mapping context?
pub(crate) mapping_context: bool,
/// Is it a simple mapping key context?
pub(crate) simple_key_context: bool,
/// The current line.
pub(crate) line: i32,
/// The current column.
pub(crate) column: i32,
/// If the last character was a whitespace?
pub(crate) whitespace: bool,
/// If the last character was an indentation character (' ', '-', '?', ':')?
pub(crate) indention: bool,
/// If an explicit document end is required?
pub(crate) open_ended: i32,
/// If the stream was already opened?
pub(crate) opened: bool,
/// If the stream was already closed?
pub(crate) closed: bool,
/// The information associated with the document nodes.
// Note: Same length as `document.nodes`.
pub(crate) anchors: Vec<Anchors>,
/// The last assigned anchor id.
pub(crate) last_anchor_id: i32,
}
impl<'a> Default for Emitter<'a> {
fn default() -> Self {
yaml_emitter_new()
}
}