This commit is contained in:
Simon Ask Ulsnes 2024-02-03 10:21:09 +01:00
parent f46efd6a29
commit 1e8de81f66
10 changed files with 323 additions and 349 deletions

View file

@ -13,10 +13,7 @@ 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;
/// Initialize a parser.
///
/// This function creates a new parser object. An application is responsible
/// for destroying the object using the yaml_parser_delete() function.
/// Create a parser.
pub fn yaml_parser_new<'r>() -> Parser<'r> {
Parser {
read_handler: None,
@ -184,7 +181,7 @@ pub fn yaml_document_start_event_new(
tag_directives_in: &[TagDirective],
implicit: bool,
) -> Event {
let tag_directives = Vec::from_iter(tag_directives_in.iter().cloned());
let tag_directives = tag_directives_in.to_vec();
Event {
data: EventData::DocumentStart {
@ -350,7 +347,7 @@ pub fn yaml_document_new(
end_implicit: bool,
) -> Document {
let nodes = Vec::with_capacity(16);
let tag_directives = Vec::from_iter(tag_directives_in.iter().cloned());
let tag_directives = tag_directives_in.to_vec();
Document {
nodes,

View file

@ -11,7 +11,8 @@
clippy::ptr_as_ptr,
clippy::single_match_else,
clippy::too_many_lines,
clippy::unreadable_literal
clippy::unreadable_literal,
clippy::manual_strip
)]
use libyaml_safer::{

View file

@ -10,7 +10,7 @@ use crate::{
/// Start a YAML stream.
///
/// This function should be used before yaml_emitter_dump() is called.
/// This function should be used before [`yaml_emitter_dump()`] is called.
pub fn yaml_emitter_open(emitter: &mut Emitter) -> Result<(), EmitterError> {
assert!(!emitter.opened);
let event = Event {
@ -24,7 +24,7 @@ pub fn yaml_emitter_open(emitter: &mut Emitter) -> Result<(), EmitterError> {
/// Finish a YAML stream.
///
/// This function should be used after yaml_emitter_dump() is called.
/// This function should be used after [`yaml_emitter_dump()`] is called.
pub fn yaml_emitter_close(emitter: &mut Emitter) -> Result<(), EmitterError> {
assert!(emitter.opened);
if emitter.closed {
@ -41,8 +41,8 @@ pub fn yaml_emitter_close(emitter: &mut Emitter) -> Result<(), EmitterError> {
/// Emit a YAML document.
///
/// The document object may be generated using the yaml_parser_load() function
/// or the yaml_document_new() function.
/// The document object may be generated using the [`yaml_parser_load()`] function
/// or the [`yaml_document_new()`] function.
pub fn yaml_emitter_dump(
emitter: &mut Emitter,
mut document: Document,

View file

@ -20,7 +20,7 @@ fn FLUSH(emitter: &mut Emitter) -> Result<(), WriterError> {
fn PUT(emitter: &mut Emitter, value: u8) -> Result<(), WriterError> {
FLUSH(emitter)?;
let ch = char::try_from(value).expect("invalid char");
let ch = char::from(value);
emitter.buffer.push(ch);
emitter.column += 1;
Ok(())
@ -111,7 +111,7 @@ fn yaml_emitter_set_emitter_error<T>(
/// Emit an event.
///
/// The event object may be generated using the yaml_parser_parse() function.
/// The event object may be generated using the [`yaml_parser_parse()`] function.
/// The emitter takes the responsibility for the event object and destroys its
/// content after it is emitted. The event object is destroyed even if the
/// function fails.
@ -801,18 +801,15 @@ fn yaml_emitter_select_scalar_style(
style = ScalarStyle::SingleQuoted;
}
}
if style == ScalarStyle::SingleQuoted {
if !scalar_analysis.single_quoted_allowed {
style = ScalarStyle::DoubleQuoted;
}
if style == ScalarStyle::SingleQuoted && !scalar_analysis.single_quoted_allowed {
style = ScalarStyle::DoubleQuoted;
}
if style == ScalarStyle::Literal || style == ScalarStyle::Folded {
if !scalar_analysis.block_allowed
if (style == ScalarStyle::Literal || style == ScalarStyle::Folded)
&& (!scalar_analysis.block_allowed
|| emitter.flow_level != 0
|| emitter.simple_key_context
{
style = ScalarStyle::DoubleQuoted;
}
|| emitter.simple_key_context)
{
style = ScalarStyle::DoubleQuoted;
}
if no_tag && !*quoted_implicit && style != ScalarStyle::Plain {
*tag_analysis = Some(TagAnalysis {
@ -855,15 +852,15 @@ fn yaml_emitter_process_tag(
if analysis.handle.is_empty() && analysis.suffix.is_empty() {
return Ok(());
}
if !analysis.handle.is_empty() {
if analysis.handle.is_empty() {
yaml_emitter_write_indicator(emitter, "!<", true, false, false)?;
yaml_emitter_write_tag_content(emitter, analysis.suffix, false)?;
yaml_emitter_write_indicator(emitter, ">", false, false, false)?;
} else {
yaml_emitter_write_tag_handle(emitter, analysis.handle)?;
if !analysis.suffix.is_empty() {
yaml_emitter_write_tag_content(emitter, analysis.suffix, false)?;
}
} else {
yaml_emitter_write_indicator(emitter, "!<", true, false, false)?;
yaml_emitter_write_tag_content(emitter, analysis.suffix, false)?;
yaml_emitter_write_indicator(emitter, ">", false, false, false)?;
}
Ok(())
}
@ -1526,7 +1523,7 @@ fn yaml_emitter_write_double_quoted_scalar(
&& !spaces
&& emitter.column > emitter.best_width
&& !first
&& !chars.clone().next().is_none()
&& chars.clone().next().is_some()
{
yaml_emitter_write_indent(emitter)?;
if is_space(chars.clone().next()) {

View file

@ -11,27 +11,19 @@
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
// clippy::cast_ptr_alignment,
clippy::cast_sign_loss,
clippy::collapsible_if,
clippy::doc_markdown,
clippy::fn_params_excessive_bools,
clippy::if_not_else,
clippy::items_after_statements,
clippy::let_underscore_untyped,
clippy::manual_range_contains,
clippy::missing_panics_doc,
clippy::missing_safety_doc,
clippy::missing_errors_doc,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::needless_pass_by_value,
clippy::nonminimal_bool,
clippy::similar_names,
clippy::struct_excessive_bools,
clippy::too_many_arguments,
clippy::too_many_lines,
clippy::unnecessary_wraps
clippy::unnecessary_wraps,
clippy::match_wildcard_for_single_variants
)]
extern crate alloc;
@ -89,9 +81,6 @@ mod tests {
#[test]
fn sanity() {
let mut parser = yaml_parser_new();
// const SANITY_INPUT: &'static str =
// "Mark McGwire:\n hr: 65\n avg: 0.278\nSammy Sosa:\n hr: 63\n avg: 0.288\n";
const SANITY_INPUT: &str = r#"
unicode: "Sosa did fine.\u263A"
control: "\b1998\t1999\t2000\n"
@ -101,6 +90,9 @@ single: '"Howdy!" he cried.'
quoted: ' # Not a ''comment''.'
tie-fighter: '|\-*-/|'
"#;
let mut parser = yaml_parser_new();
// const SANITY_INPUT: &'static str =
// "Mark McGwire:\n hr: 65\n avg: 0.278\nSammy Sosa:\n hr: 63\n avg: 0.288\n";
let mut read_in = SANITY_INPUT.as_bytes();
yaml_parser_set_input_string(&mut parser, &mut read_in);
let _doc = yaml_parser_load(&mut parser).unwrap();

View file

@ -15,9 +15,9 @@ use crate::{
/// If the produced document has no root node, it means that the document end
/// has been reached.
///
/// An application must not alternate the calls of yaml_parser_load() with the
/// calls of yaml_parser_scan() or yaml_parser_parse(). Doing this will break
/// the parser.
/// An application must not alternate the calls of [`yaml_parser_load()`] with
/// the calls of [`yaml_parser_scan()`] or [`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);
document.nodes.reserve(16);

View file

@ -126,17 +126,16 @@ pub(crate) fn is_ascii(ch: char) -> bool {
pub(crate) fn is_printable(ch: char) -> bool {
match ch {
'\u{feff}' | '\u{fffe}' | '\u{ffff}' => false,
// ASCII
'\x0a' | '\x20'..='\x7e' => true,
'\u{00a0}'..='\u{00bf}' => true,
'\u{00c0}'..='\u{cfff}' => true,
'\u{d000}'..='\u{d7ff}' => true,
'\u{e000}'..='\u{efff}' => true,
'\u{feff}' => false,
'\u{fffe}' => false,
'\u{ffff}' => false,
'\u{f000}'..='\u{fffd}' => true,
'\u{10000}'..='\u{10ffff}' => true,
'\x0a'
| '\x20'..='\x7e'
| '\u{00a0}'..='\u{00bf}'
| '\u{00c0}'..='\u{cfff}'
| '\u{d000}'..='\u{d7ff}'
| '\u{e000}'..='\u{efff}'
| '\u{f000}'..='\u{fffd}'
| '\u{10000}'..='\u{10ffff}' => true,
_ => false,
}
}
@ -225,10 +224,10 @@ macro_rules! IS_BREAK_AT {
}
pub(crate) fn is_break(ch: impl Into<Option<char>>) -> bool {
match ch.into() {
Some('\r' | '\n' | '\u{0085}' | '\u{2028}' | '\u{2029}') => true,
_ => false,
}
matches!(
ch.into(),
Some('\r' | '\n' | '\u{0085}' | '\u{2028}' | '\u{2029}')
)
}
pub(crate) fn is_breakz(ch: impl Into<Option<char>>) -> bool {

View file

@ -58,12 +58,13 @@ fn SKIP_TOKEN(parser: &mut Parser) {
/// Parse the input stream and produce the next parsing event.
///
/// Call the function subsequently to produce a sequence of events corresponding
/// to the input stream. The initial event has the type YAML_STREAM_START_EVENT
/// while the ending event has the type YAML_STREAM_END_EVENT.
/// to the input stream. The initial event has the type
/// [`EventData::StreamStart`] while the ending event has the type
/// [`EventData::StreamEnd`].
///
/// An application must not alternate the calls of yaml_parser_parse() with the
/// calls of yaml_parser_scan() or yaml_parser_load(). Doing this will break the
/// parser.
/// An application must not alternate the calls of [`yaml_parser_parse()`] with
/// the calls of [`yaml_parser_scan()`] or [`yaml_parser_load()`]. Doing this
/// will break the parser.
pub fn yaml_parser_parse(parser: &mut Parser) -> Result<Event, ParserError> {
if parser.stream_end_produced || parser.state == ParserState::End {
return Ok(Event {
@ -197,12 +198,7 @@ fn yaml_parser_parse_document_start(
Some(&mut tag_directives),
)?;
token = PEEK_TOKEN(parser)?;
if !token.data.is_document_start() {
return yaml_parser_set_parser_error(
"did not find expected <document start>",
token.start_mark,
);
} else {
if token.data.is_document_start() {
end_mark = token.end_mark;
let event = Event {
data: EventData::DocumentStart {
@ -216,7 +212,9 @@ fn yaml_parser_parse_document_start(
parser.states.push(ParserState::DocumentEnd);
parser.state = ParserState::DocumentContent;
SKIP_TOKEN(parser);
return Ok(event);
Ok(event)
} else {
yaml_parser_set_parser_error("did not find expected <document start>", token.start_mark)
}
} else {
let event = Event {
@ -759,11 +757,10 @@ fn yaml_parser_parse_flow_mapping_key(
{
parser.states.push(ParserState::FlowMappingValue);
return yaml_parser_parse_node(parser, false, false);
} else {
let mark = token.start_mark;
parser.state = ParserState::FlowMappingValue;
return yaml_parser_process_empty_scalar(mark);
}
let mark = token.start_mark;
parser.state = ParserState::FlowMappingValue;
return yaml_parser_process_empty_scalar(mark);
} else if !token.data.is_flow_mapping_end() {
parser.states.push(ParserState::FlowMappingEmptyValue);
return yaml_parser_parse_node(parser, false, false);
@ -851,12 +848,11 @@ fn yaml_parser_process_directives(
return yaml_parser_set_parser_error("found duplicate %YAML directive", mark);
} else if *major != 1 || *minor != 1 && *minor != 2 {
return yaml_parser_set_parser_error("found incompatible YAML document", mark);
} else {
version_directive = Some(VersionDirective {
major: *major,
minor: *minor,
});
}
version_directive = Some(VersionDirective {
major: *major,
minor: *minor,
});
} else if let TokenData::TagDirective { handle, prefix } = &token.data {
let value = TagDirective {
// TODO: Get rid of these clones by consuming tokens by value.

View file

@ -83,12 +83,13 @@ fn READ_LINE_STRING(parser: &mut Parser, string: &mut String) {
/// Scan the input stream and produce the next token.
///
/// Call the function subsequently to produce a sequence of tokens corresponding
/// to the input stream. The initial token has the type YAML_STREAM_START_TOKEN
/// while the ending token has the type YAML_STREAM_END_TOKEN.
/// to the input stream. The initial token has the type
/// [`TokenData::StreamStart`] while the ending token has the type
/// [`TokenData::StreamEnd`].
///
/// An application must not alternate the calls of yaml_parser_scan() with the
/// calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break
/// the parser.
/// An application must not alternate the calls of [`yaml_parser_scan()`] with
/// the calls of [`yaml_parser_parse()`] or [`yaml_parser_load()`]. Doing this
/// will break the parser.
pub fn yaml_parser_scan(parser: &mut Parser) -> Result<Token, ScannerError> {
if parser.stream_end_produced {
return Ok(Token {
@ -327,7 +328,7 @@ fn yaml_parser_increase_flow_level(parser: &mut Parser) -> Result<(), ScannerErr
};
parser.simple_keys.push(empty_simple_key);
assert!(
!(parser.flow_level == i32::MAX),
parser.flow_level != i32::MAX,
"parser.flow_level integer overflow"
);
parser.flow_level += 1;
@ -353,7 +354,7 @@ fn yaml_parser_roll_indent(
}
if parser.indent < column as i32 {
parser.indents.push(parser.indent);
assert!(!(column > i32::MAX as i64), "integer overflow");
assert!(column <= i32::MAX as i64, "integer overflow");
parser.indent = column as i32;
let token = Token {
data,
@ -363,10 +364,9 @@ fn yaml_parser_roll_indent(
if number == -1_i64 {
parser.tokens.push_back(token);
} else {
parser.tokens.insert(
(number as usize).wrapping_sub(parser.tokens_parsed),
token,
);
parser
.tokens
.insert((number as usize).wrapping_sub(parser.tokens_parsed), token);
}
}
Ok(())
@ -764,19 +764,19 @@ fn yaml_parser_scan_directive(parser: &mut Parser, token: &mut Token) -> Result<
}
}
if !IS_BREAKZ!(parser.buffer) {
if IS_BREAKZ!(parser.buffer) {
if IS_BREAK!(parser.buffer) {
CACHE(parser, 2)?;
SKIP_LINE(parser);
}
Ok(())
} else {
yaml_parser_set_scanner_error(
parser,
"while scanning a directive",
start_mark,
"did not find expected comment or line break",
)
} else {
if IS_BREAK!(parser.buffer) {
CACHE(parser, 2)?;
SKIP_LINE(parser);
}
Ok(())
}
}
@ -897,26 +897,25 @@ fn yaml_parser_scan_tag_directive_value(
start_mark,
"did not find expected whitespace",
);
} else {
while IS_BLANK!(parser.buffer) {
SKIP(parser);
CACHE(parser, 1)?;
}
let prefix_value = yaml_parser_scan_tag_uri(parser, true, true, None, start_mark)?;
CACHE(parser, 1)?;
if !IS_BLANKZ!(parser.buffer) {
return yaml_parser_set_scanner_error(
parser,
"while scanning a %TAG directive",
start_mark,
"did not find expected whitespace or line break",
);
} else {
return Ok((handle_value, prefix_value));
}
}
while IS_BLANK!(parser.buffer) {
SKIP(parser);
CACHE(parser, 1)?;
}
let prefix_value = yaml_parser_scan_tag_uri(parser, true, true, None, start_mark)?;
CACHE(parser, 1)?;
if !IS_BLANKZ!(parser.buffer) {
return yaml_parser_set_scanner_error(
parser,
"while scanning a %TAG directive",
start_mark,
"did not find expected whitespace or line break",
);
}
return Ok((handle_value, prefix_value));
}
}
}
@ -955,10 +954,10 @@ fn yaml_parser_scan_anchor(
{
yaml_parser_set_scanner_error(
parser,
if !scan_alias_instead_of_anchor {
"while scanning an anchor"
} else {
if scan_alias_instead_of_anchor {
"while scanning an alias"
} else {
"while scanning an anchor"
},
start_mark,
"did not find expected alphabetic or numeric character",
@ -998,9 +997,8 @@ fn yaml_parser_scan_tag(parser: &mut Parser, token: &mut Token) -> Result<(), Sc
start_mark,
"did not find the expected '>'",
);
} else {
SKIP(parser);
}
SKIP(parser);
} else {
handle = yaml_parser_scan_tag_handle(parser, false, start_mark)?;
if handle.starts_with('!') && handle.len() > 1 && handle.ends_with('!') {
@ -1023,9 +1021,8 @@ fn yaml_parser_scan_tag(parser: &mut Parser, token: &mut Token) -> Result<(), Sc
start_mark,
"did not find expected whitespace or line break",
);
} else {
panic!("TODO: What is expected here?");
}
panic!("TODO: What is expected here?");
}
let end_mark: Mark = parser.mark;
@ -1211,7 +1208,7 @@ fn yaml_parser_scan_uri_escapes(
SKIP(parser);
SKIP(parser);
width -= 1;
if !(width != 0) {
if width == 0 {
break;
}
}
@ -1248,10 +1245,9 @@ fn yaml_parser_scan_block_scalar(
start_mark,
"found an indentation indicator equal to 0",
);
} else {
increment = AS_DIGIT!(parser.buffer) as i32;
SKIP(parser);
}
increment = AS_DIGIT!(parser.buffer) as i32;
SKIP(parser);
}
} else if IS_DIGIT!(parser.buffer) {
if CHECK!(parser.buffer, '0') {
@ -1261,14 +1257,13 @@ fn yaml_parser_scan_block_scalar(
start_mark,
"found an indentation indicator equal to 0",
);
} else {
increment = AS_DIGIT!(parser.buffer) as i32;
}
increment = AS_DIGIT!(parser.buffer) as i32;
SKIP(parser);
CACHE(parser, 1)?;
if CHECK!(parser.buffer, '+') || CHECK!(parser.buffer, '-') {
chomping = if CHECK!(parser.buffer, '+') { 1 } else { -1 };
SKIP(parser);
CACHE(parser, 1)?;
if CHECK!(parser.buffer, '+') || CHECK!(parser.buffer, '-') {
chomping = if CHECK!(parser.buffer, '+') { 1 } else { -1 };
SKIP(parser);
}
}
}
@ -1324,7 +1319,7 @@ fn yaml_parser_scan_block_scalar(
CACHE(parser, 1)?;
loop {
if !(parser.mark.column as i32 == indent && !IS_Z!(parser.buffer)) {
if parser.mark.column as i32 != indent || IS_Z!(parser.buffer) {
break;
}
trailing_blank = IS_BLANK!(parser.buffer) as i32;
@ -1463,194 +1458,191 @@ fn yaml_parser_scan_flow_scalar(
start_mark,
"found unexpected end of stream",
);
} else {
CACHE(parser, 2)?;
leading_blanks = false;
while !IS_BLANKZ!(parser.buffer) {
if single && CHECK_AT!(parser.buffer, '\'', 0) && CHECK_AT!(parser.buffer, '\'', 1)
{
string.push('\'');
}
CACHE(parser, 2)?;
leading_blanks = false;
while !IS_BLANKZ!(parser.buffer) {
if single && CHECK_AT!(parser.buffer, '\'', 0) && CHECK_AT!(parser.buffer, '\'', 1) {
string.push('\'');
SKIP(parser);
SKIP(parser);
} else {
if CHECK!(parser.buffer, if single { '\'' } else { '"' }) {
break;
}
if !single && CHECK!(parser.buffer, '\\') && IS_BREAK_AT!(parser.buffer, 1) {
CACHE(parser, 3)?;
SKIP(parser);
SKIP(parser);
} else {
if CHECK!(parser.buffer, if single { '\'' } else { '"' }) {
break;
}
if !single && CHECK!(parser.buffer, '\\') && IS_BREAK_AT!(parser.buffer, 1) {
CACHE(parser, 3)?;
SKIP(parser);
SKIP_LINE(parser);
leading_blanks = true;
break;
} else if !single && CHECK!(parser.buffer, '\\') {
let mut code_length = 0usize;
match parser.buffer.get(1).copied().unwrap() {
'0' => {
string.push('\0');
}
'a' => {
string.push('\x07');
}
'b' => {
string.push('\x08');
}
't' | '\t' => {
string.push('\t');
}
'n' => {
string.push('\n');
}
'v' => {
string.push('\x0B');
}
'f' => {
string.push('\x0C');
}
'r' => {
string.push('\r');
}
'e' => {
string.push('\x1B');
}
' ' => {
string.push(' ');
}
'"' => {
string.push('"');
}
'/' => {
string.push('/');
}
'\\' => {
string.push('\\');
}
// NEL (#x85)
'N' => {
string.push('\u{0085}');
}
// #xA0
'_' => {
string.push('\u{00a0}');
// string.push('\xC2');
// string.push('\xA0');
}
// LS (#x2028)
'L' => {
string.push('\u{2028}');
// string.push('\xE2');
// string.push('\x80');
// string.push('\xA8');
}
// PS (#x2029)
'P' => {
string.push('\u{2029}');
// string.push('\xE2');
// string.push('\x80');
// string.push('\xA9');
}
'x' => {
code_length = 2;
}
'u' => {
code_length = 4;
}
'U' => {
code_length = 8;
}
_ => {
return yaml_parser_set_scanner_error(
parser,
"while parsing a quoted scalar",
start_mark,
"found unknown escape character",
);
}
SKIP_LINE(parser);
leading_blanks = true;
break;
} else if !single && CHECK!(parser.buffer, '\\') {
let mut code_length = 0usize;
match parser.buffer.get(1).copied().unwrap() {
'0' => {
string.push('\0');
}
SKIP(parser);
SKIP(parser);
if code_length != 0 {
let mut value: u32 = 0;
let mut k = 0;
CACHE(parser, code_length)?;
while k < code_length {
if !IS_HEX_AT!(parser.buffer, k) {
return yaml_parser_set_scanner_error(
parser,
"while parsing a quoted scalar",
start_mark,
"did not find expected hexdecimal number",
);
} else {
value = (value << 4) + AS_HEX_AT!(parser.buffer, k);
k += 1;
}
}
if let Some(ch) = char::from_u32(value) {
string.push(ch);
} else {
'a' => {
string.push('\x07');
}
'b' => {
string.push('\x08');
}
't' | '\t' => {
string.push('\t');
}
'n' => {
string.push('\n');
}
'v' => {
string.push('\x0B');
}
'f' => {
string.push('\x0C');
}
'r' => {
string.push('\r');
}
'e' => {
string.push('\x1B');
}
' ' => {
string.push(' ');
}
'"' => {
string.push('"');
}
'/' => {
string.push('/');
}
'\\' => {
string.push('\\');
}
// NEL (#x85)
'N' => {
string.push('\u{0085}');
}
// #xA0
'_' => {
string.push('\u{00a0}');
// string.push('\xC2');
// string.push('\xA0');
}
// LS (#x2028)
'L' => {
string.push('\u{2028}');
// string.push('\xE2');
// string.push('\x80');
// string.push('\xA8');
}
// PS (#x2029)
'P' => {
string.push('\u{2029}');
// string.push('\xE2');
// string.push('\x80');
// string.push('\xA9');
}
'x' => {
code_length = 2;
}
'u' => {
code_length = 4;
}
'U' => {
code_length = 8;
}
_ => {
return yaml_parser_set_scanner_error(
parser,
"while parsing a quoted scalar",
start_mark,
"found unknown escape character",
);
}
}
SKIP(parser);
SKIP(parser);
if code_length != 0 {
let mut value: u32 = 0;
let mut k = 0;
CACHE(parser, code_length)?;
while k < code_length {
if !IS_HEX_AT!(parser.buffer, k) {
return yaml_parser_set_scanner_error(
parser,
"while parsing a quoted scalar",
start_mark,
"found invalid Unicode character escape code",
"did not find expected hexdecimal number",
);
}
value = (value << 4) + AS_HEX_AT!(parser.buffer, k);
k += 1;
}
if let Some(ch) = char::from_u32(value) {
string.push(ch);
} else {
return yaml_parser_set_scanner_error(
parser,
"while parsing a quoted scalar",
start_mark,
"found invalid Unicode character escape code",
);
}
k = 0;
while k < code_length {
SKIP(parser);
k += 1;
}
k = 0;
while k < code_length {
SKIP(parser);
k += 1;
}
} else {
READ_STRING(parser, &mut string);
}
}
CACHE(parser, 2)?;
}
CACHE(parser, 1)?;
if CHECK!(parser.buffer, if single { '\'' } else { '"' }) {
break;
}
CACHE(parser, 1)?;
while IS_BLANK!(parser.buffer) || IS_BREAK!(parser.buffer) {
if IS_BLANK!(parser.buffer) {
if !leading_blanks {
READ_STRING(parser, &mut whitespaces);
} else {
SKIP(parser);
}
} else {
CACHE(parser, 2)?;
if !leading_blanks {
whitespaces.clear();
READ_LINE_STRING(parser, &mut leading_break);
leading_blanks = true;
} else {
READ_LINE_STRING(parser, &mut trailing_breaks);
}
READ_STRING(parser, &mut string);
}
CACHE(parser, 1)?;
}
if leading_blanks {
if leading_break.starts_with('\n') {
if trailing_breaks.is_empty() {
string.push(' ');
} else {
string.push_str(&trailing_breaks);
trailing_breaks.clear();
}
leading_break.clear();
CACHE(parser, 2)?;
}
CACHE(parser, 1)?;
if CHECK!(parser.buffer, if single { '\'' } else { '"' }) {
break;
}
CACHE(parser, 1)?;
while IS_BLANK!(parser.buffer) || IS_BREAK!(parser.buffer) {
if IS_BLANK!(parser.buffer) {
if leading_blanks {
SKIP(parser);
} else {
string.push_str(&leading_break);
string.push_str(&trailing_breaks);
leading_break.clear();
trailing_breaks.clear();
READ_STRING(parser, &mut whitespaces);
}
} else {
string.push_str(&whitespaces);
whitespaces.clear();
CACHE(parser, 2)?;
if leading_blanks {
READ_LINE_STRING(parser, &mut trailing_breaks);
} else {
whitespaces.clear();
READ_LINE_STRING(parser, &mut leading_break);
leading_blanks = true;
}
}
CACHE(parser, 1)?;
}
if leading_blanks {
if leading_break.starts_with('\n') {
if trailing_breaks.is_empty() {
string.push(' ');
} else {
string.push_str(&trailing_breaks);
trailing_breaks.clear();
}
leading_break.clear();
} else {
string.push_str(&leading_break);
string.push_str(&trailing_breaks);
leading_break.clear();
trailing_breaks.clear();
}
} else {
string.push_str(&whitespaces);
whitespaces.clear();
}
}
@ -1716,43 +1708,43 @@ fn yaml_parser_scan_plain_scalar(
start_mark,
"found unexpected ':'",
);
} else {
if CHECK!(parser.buffer, ':') && IS_BLANKZ_AT!(parser.buffer, 1)
|| parser.flow_level != 0
&& (CHECK!(parser.buffer, ',')
|| CHECK!(parser.buffer, '[')
|| CHECK!(parser.buffer, ']')
|| CHECK!(parser.buffer, '{')
|| CHECK!(parser.buffer, '}'))
{
break;
}
if leading_blanks || !whitespaces.is_empty() {
if leading_blanks {
if leading_break.starts_with('\n') {
if trailing_breaks.is_empty() {
string.push(' ');
} else {
string.push_str(&trailing_breaks);
trailing_breaks.clear();
}
leading_break.clear();
}
if CHECK!(parser.buffer, ':') && IS_BLANKZ_AT!(parser.buffer, 1)
|| parser.flow_level != 0
&& (CHECK!(parser.buffer, ',')
|| CHECK!(parser.buffer, '[')
|| CHECK!(parser.buffer, ']')
|| CHECK!(parser.buffer, '{')
|| CHECK!(parser.buffer, '}'))
{
break;
}
if leading_blanks || !whitespaces.is_empty() {
if leading_blanks {
if leading_break.starts_with('\n') {
if trailing_breaks.is_empty() {
string.push(' ');
} else {
string.push_str(&leading_break);
string.push_str(&trailing_breaks);
leading_break.clear();
trailing_breaks.clear();
}
leading_blanks = false;
leading_break.clear();
} else {
string.push_str(&whitespaces);
whitespaces.clear();
string.push_str(&leading_break);
string.push_str(&trailing_breaks);
leading_break.clear();
trailing_breaks.clear();
}
leading_blanks = false;
} else {
string.push_str(&whitespaces);
whitespaces.clear();
}
READ_STRING(parser, &mut string);
end_mark = parser.mark;
CACHE(parser, 2)?;
}
READ_STRING(parser, &mut string);
end_mark = parser.mark;
CACHE(parser, 2)?;
}
if !(IS_BLANK!(parser.buffer) || IS_BREAK!(parser.buffer)) {
break;
@ -1777,12 +1769,12 @@ fn yaml_parser_scan_plain_scalar(
} else {
CACHE(parser, 2)?;
if !leading_blanks {
if leading_blanks {
READ_LINE_STRING(parser, &mut trailing_breaks);
} else {
whitespaces.clear();
READ_LINE_STRING(parser, &mut leading_break);
leading_blanks = true;
} else {
READ_LINE_STRING(parser, &mut trailing_breaks);
}
}
CACHE(parser, 1)?;

View file

@ -6,29 +6,29 @@ use crate::{api::yaml_parser_new, yaml_emitter_new};
pub use self::Encoding::*;
/// The tag `!!null`` with the only possible value: `null`.
/// 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`.
/// 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.
/// The tag `!!str` for string values.
pub const STR_TAG: &str = "tag:yaml.org,2002:str";
/// The tag `!!int`` for integer values.
/// The tag `!!int` for integer values.
pub const INT_TAG: &str = "tag:yaml.org,2002:int";
/// The tag `!!float`` for float values.
/// The tag `!!float` for float values.
pub const FLOAT_TAG: &str = "tag:yaml.org,2002:float";
/// The tag `!!timestamp`` for date and time values.
/// 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.
/// 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.
/// The tag `!!map` is used to denote mapping.
pub const MAP_TAG: &str = "tag:yaml.org,2002:map";
/// The default scalar tag is `!!str``.
/// The default scalar tag is `!!str`.
pub const DEFAULT_SCALAR_TAG: &str = STR_TAG;
/// The default sequence tag is `!!seq``.
/// The default sequence tag is `!!seq`.
pub const DEFAULT_SEQUENCE_TAG: &str = SEQ_TAG;
/// The default mapping tag is `!!map``.
/// The default mapping tag is `!!map`.
pub const DEFAULT_MAPPING_TAG: &str = MAP_TAG;
/// The version directive data.