mirror of
https://github.com/simonask/libyaml-safer
synced 2024-11-22 19:33:03 +00:00
Rustify module organization
This commit is contained in:
parent
1ffb036601
commit
5b9dcd7a15
12 changed files with 1183 additions and 1233 deletions
516
src/api.rs
516
src/api.rs
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
244
src/document.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
231
src/emitter.rs
231
src/emitter.rs
|
@ -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
269
src/event.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
167
src/lib.rs
167
src/lib.rs
|
@ -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!(
|
||||
|
|
|
@ -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 {
|
||||
|
|
198
src/parser.rs
198
src/parser.rs
|
@ -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
|
||||
|
|
|
@ -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
91
src/token.rs
Normal 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,
|
||||
},
|
||||
}
|
654
src/yaml.rs
654
src/yaml.rs
|
@ -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()
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue