Have ScanError::new take a String.

Internally, `ScanError` stores a `String`. Having `new` take a `&str`
misleadingly indicates that it stores a `&str`. This commit changes
`new` so that it takes a `String`, and adds a convenience method,
`new_str` that takes a `&str` and allocates a `String` for it.
This commit is contained in:
Ethiraric 2024-04-07 02:04:45 +02:00
parent 3b1dee5ef7
commit cbba46fa72
2 changed files with 88 additions and 73 deletions

View file

@ -348,7 +348,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
let token = self.scanner.next(); let token = self.scanner.next();
match token { match token {
None => match self.scanner.get_error() { None => match self.scanner.get_error() {
None => Err(ScanError::new(self.scanner.mark(), "unexpected eof")), None => Err(ScanError::new_str(self.scanner.mark(), "unexpected eof")),
Some(e) => Err(e), Some(e) => Err(e),
}, },
Some(tok) => Ok(tok), Some(tok) => Ok(tok),
@ -402,7 +402,10 @@ impl<T: Iterator<Item = char>> Parser<T> {
if !self.scanner.stream_started() { if !self.scanner.stream_started() {
let (ev, mark) = self.next_event_impl()?; let (ev, mark) = self.next_event_impl()?;
if ev != Event::StreamStart { if ev != Event::StreamStart {
return Err(ScanError::new(mark, "did not find expected <stream-start>")); return Err(ScanError::new_str(
mark,
"did not find expected <stream-start>",
));
} }
recv.on_event(ev, mark); recv.on_event(ev, mark);
} }
@ -435,7 +438,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
recv: &mut R, recv: &mut R,
) -> Result<(), ScanError> { ) -> Result<(), ScanError> {
if first_ev != Event::DocumentStart { if first_ev != Event::DocumentStart {
return Err(ScanError::new( return Err(ScanError::new_str(
mark, mark,
"did not find expected <document-start>", "did not find expected <document-start>",
)); ));
@ -561,7 +564,10 @@ impl<T: Iterator<Item = char>> Parser<T> {
self.skip(); self.skip();
Ok((Event::StreamStart, mark)) Ok((Event::StreamStart, mark))
} }
Token(mark, _) => Err(ScanError::new(mark, "did not find expected <stream-start>")), Token(mark, _) => Err(ScanError::new_str(
mark,
"did not find expected <stream-start>",
)),
} }
} }
@ -606,17 +612,17 @@ impl<T: Iterator<Item = char>> Parser<T> {
Token(mark, TokenType::VersionDirective(_, _)) => { Token(mark, TokenType::VersionDirective(_, _)) => {
// XXX parsing with warning according to spec // XXX parsing with warning according to spec
//if major != 1 || minor > 2 { //if major != 1 || minor > 2 {
// return Err(ScanError::new(tok.0, // return Err(ScanError::new_str(tok.0,
// "found incompatible YAML document")); // "found incompatible YAML document"));
//} //}
if version_directive_received { if version_directive_received {
return Err(ScanError::new(*mark, "duplicate version directive")); return Err(ScanError::new_str(*mark, "duplicate version directive"));
} }
version_directive_received = true; version_directive_received = true;
} }
Token(mark, TokenType::TagDirective(handle, prefix)) => { Token(mark, TokenType::TagDirective(handle, prefix)) => {
if tags.contains_key(handle) { if tags.contains_key(handle) {
return Err(ScanError::new(*mark, "the TAG directive must only be given at most once per handle in the same document")); return Err(ScanError::new_str(*mark, "the TAG directive must only be given at most once per handle in the same document"));
} }
tags.insert(handle.to_string(), prefix.to_string()); tags.insert(handle.to_string(), prefix.to_string());
} }
@ -637,7 +643,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
self.skip(); self.skip();
Ok((Event::DocumentStart, mark)) Ok((Event::DocumentStart, mark))
} }
Token(mark, _) => Err(ScanError::new( Token(mark, _) => Err(ScanError::new_str(
mark, mark,
"did not find expected <document start>", "did not find expected <document start>",
)), )),
@ -682,7 +688,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
if let Token(mark, TokenType::VersionDirective(..) | TokenType::TagDirective(..)) = if let Token(mark, TokenType::VersionDirective(..) | TokenType::TagDirective(..)) =
*self.peek_token()? *self.peek_token()?
{ {
return Err(ScanError::new( return Err(ScanError::new_str(
mark, mark,
"missing explicit document end marker before directive", "missing explicit document end marker before directive",
)); ));
@ -696,7 +702,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
fn register_anchor(&mut self, name: String, _: &Marker) -> usize { fn register_anchor(&mut self, name: String, _: &Marker) -> usize {
// anchors can be overridden/reused // anchors can be overridden/reused
// if self.anchors.contains_key(name) { // if self.anchors.contains_key(name) {
// return Err(ScanError::new(*mark, // return Err(ScanError::new_str(*mark,
// "while parsing anchor, found duplicated anchor")); // "while parsing anchor, found duplicated anchor"));
// } // }
let new_id = self.anchor_id_count; let new_id = self.anchor_id_count;
@ -714,7 +720,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
if let Token(mark, TokenType::Alias(name)) = self.fetch_token() { if let Token(mark, TokenType::Alias(name)) = self.fetch_token() {
match self.anchors.get(&name) { match self.anchors.get(&name) {
None => { None => {
return Err(ScanError::new( return Err(ScanError::new_str(
mark, mark,
"while parsing node, found unknown anchor", "while parsing node, found unknown anchor",
)) ))
@ -788,7 +794,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
self.pop_state(); self.pop_state();
Ok((Event::empty_scalar_with_anchor(anchor_id, tag), mark)) Ok((Event::empty_scalar_with_anchor(anchor_id, tag), mark))
} }
Token(mark, _) => Err(ScanError::new( Token(mark, _) => Err(ScanError::new_str(
mark, mark,
"while parsing a node, did not find expected node content", "while parsing a node, did not find expected node content",
)), )),
@ -826,7 +832,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
self.skip(); self.skip();
Ok((Event::MappingEnd, mark)) Ok((Event::MappingEnd, mark))
} }
Token(mark, _) => Err(ScanError::new( Token(mark, _) => Err(ScanError::new_str(
mark, mark,
"while parsing a block mapping, did not find expected key", "while parsing a block mapping, did not find expected key",
)), )),
@ -868,7 +874,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
if !first { if !first {
match *self.peek_token()? { match *self.peek_token()? {
Token(_, TokenType::FlowEntry) => self.skip(), Token(_, TokenType::FlowEntry) => self.skip(),
Token(mark, _) => return Err(ScanError::new( Token(mark, _) => return Err(ScanError::new_str(
mark, mark,
"while parsing a flow mapping, did not find expected ',' or '}'", "while parsing a flow mapping, did not find expected ',' or '}'",
)), )),
@ -954,7 +960,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
self.skip(); self.skip();
} }
Token(mark, _) if !first => { Token(mark, _) if !first => {
return Err(ScanError::new( return Err(ScanError::new_str(
mark, mark,
"while parsing a flow sequence, expected ',' or ']'", "while parsing a flow sequence, expected ',' or ']'",
)); ));
@ -1026,7 +1032,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
self.parse_node(true, false) self.parse_node(true, false)
} }
} }
Token(mark, _) => Err(ScanError::new( Token(mark, _) => Err(ScanError::new_str(
mark, mark,
"while parsing a block collection, did not find expected '-' indicator", "while parsing a block collection, did not find expected '-' indicator",
)), )),
@ -1112,7 +1118,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
// If the handle is of the form "!foo!", this cannot be a local handle and we need // If the handle is of the form "!foo!", this cannot be a local handle and we need
// to error. // to error.
if handle.len() >= 2 && handle.starts_with('!') && handle.ends_with('!') { if handle.len() >= 2 && handle.starts_with('!') && handle.ends_with('!') {
Err(ScanError::new(mark, "the handle wasn't declared")) Err(ScanError::new_str(mark, "the handle wasn't declared"))
} else { } else {
Ok(Tag { Ok(Tag {
handle: handle.to_string(), handle: handle.to_string(),

View file

@ -88,7 +88,13 @@ pub struct ScanError {
impl ScanError { impl ScanError {
/// Create a new error from a location and an error string. /// Create a new error from a location and an error string.
#[must_use] #[must_use]
pub fn new(loc: Marker, info: &str) -> ScanError { pub fn new(loc: Marker, info: String) -> ScanError {
ScanError { mark: loc, info }
}
/// Convenience alias for string slices.
#[must_use]
pub fn new_str(loc: Marker, info: &str) -> ScanError {
ScanError { ScanError {
mark: loc, mark: loc,
info: info.to_owned(), info: info.to_owned(),
@ -674,7 +680,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
self.fetch_document_indicator(TokenType::DocumentEnd)?; self.fetch_document_indicator(TokenType::DocumentEnd)?;
self.skip_ws_to_eol(SkipTabs::Yes)?; self.skip_ws_to_eol(SkipTabs::Yes)?;
if !is_breakz(self.ch()) { if !is_breakz(self.ch()) {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"invalid content after document end marker", "invalid content after document end marker",
)); ));
@ -683,7 +689,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
if (self.mark.col as isize) < self.indent { if (self.mark.col as isize) < self.indent {
return Err(ScanError::new(self.mark, "invalid indentation")); return Err(ScanError::new_str(self.mark, "invalid indentation"));
} }
let c = self.buffer[0]; let c = self.buffer[0];
@ -720,7 +726,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
'%' | '@' | '`' => Err(ScanError::new( '%' | '@' | '`' => Err(ScanError::new(
self.mark, self.mark,
&format!("unexpected character: `{c}'"), format!("unexpected character: `{c}'"),
)), )),
_ => self.fetch_plain_scalar(), _ => self.fetch_plain_scalar(),
} }
@ -738,7 +744,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
self.fetch_more_tokens()?; self.fetch_more_tokens()?;
} }
let Some(t) = self.tokens.pop_front() else { let Some(t) = self.tokens.pop_front() else {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"did not find expected next token", "did not find expected next token",
)); ));
@ -798,7 +804,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
&& (sk.mark.line < self.mark.line || sk.mark.index + 1024 < self.mark.index) && (sk.mark.line < self.mark.line || sk.mark.index + 1024 < self.mark.index)
{ {
if sk.required { if sk.required {
return Err(ScanError::new(self.mark, "simple key expect ':'")); return Err(ScanError::new_str(self.mark, "simple key expect ':'"));
} }
sk.possible = false; sk.possible = false;
} }
@ -828,7 +834,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
self.skip_ws_to_eol(SkipTabs::Yes)?; self.skip_ws_to_eol(SkipTabs::Yes)?;
// If we have content on that line with a tab, return an error. // If we have content on that line with a tab, return an error.
if !is_breakz(self.ch()) { if !is_breakz(self.ch()) {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"tabs disallowed within this context (block indentation)", "tabs disallowed within this context (block indentation)",
)); ));
@ -884,7 +890,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
if need_whitespace { if need_whitespace {
Err(ScanError::new(self.mark(), "expected whitespace")) Err(ScanError::new_str(self.mark(), "expected whitespace"))
} else { } else {
Ok(()) Ok(())
} }
@ -906,7 +912,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
// YAML comments must be preceded by whitespace. // YAML comments must be preceded by whitespace.
'#' if !encountered_tab && !has_yaml_ws => { '#' if !encountered_tab && !has_yaml_ws => {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"comments must be separated from other tokens by whitespace", "comments must be separated from other tokens by whitespace",
)); ));
@ -944,7 +950,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
// had. If one was required, however, that was an error and we must propagate it. // had. If one was required, however, that was an error and we must propagate it.
for sk in &mut self.simple_keys { for sk in &mut self.simple_keys {
if sk.required && sk.possible { if sk.required && sk.possible {
return Err(ScanError::new(self.mark, "simple key expected")); return Err(ScanError::new_str(self.mark, "simple key expected"));
} }
sk.possible = false; sk.possible = false;
} }
@ -991,7 +997,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
start_mark, start_mark,
TokenType::TagDirective(String::new(), String::new()), TokenType::TagDirective(String::new(), String::new()),
) )
// return Err(ScanError::new(start_mark, // return Err(ScanError::new_str(start_mark,
// "while scanning a directive, found unknown directive name")) // "while scanning a directive, found unknown directive name"))
} }
}; };
@ -999,7 +1005,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
self.skip_ws_to_eol(SkipTabs::Yes)?; self.skip_ws_to_eol(SkipTabs::Yes)?;
if !is_breakz(self.ch()) { if !is_breakz(self.ch()) {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"while scanning a directive, did not find expected comment or line break", "while scanning a directive, did not find expected comment or line break",
)); ));
@ -1022,7 +1028,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
let major = self.scan_version_directive_number(mark)?; let major = self.scan_version_directive_number(mark)?;
if self.ch() != '.' { if self.ch() != '.' {
return Err(ScanError::new( return Err(ScanError::new_str(
*mark, *mark,
"while scanning a YAML directive, did not find expected digit or '.' character", "while scanning a YAML directive, did not find expected digit or '.' character",
)); ));
@ -1043,14 +1049,14 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
if string.is_empty() { if string.is_empty() {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"while scanning a directive, could not find expected directive name", "while scanning a directive, could not find expected directive name",
)); ));
} }
if !is_blank_or_breakz(self.ch()) { if !is_blank_or_breakz(self.ch()) {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"while scanning a directive, found unexpected non-alphabetical character", "while scanning a directive, found unexpected non-alphabetical character",
)); ));
@ -1064,7 +1070,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
let mut length = 0usize; let mut length = 0usize;
while let Some(digit) = self.look_ch().to_digit(10) { while let Some(digit) = self.look_ch().to_digit(10) {
if length + 1 > 9 { if length + 1 > 9 {
return Err(ScanError::new( return Err(ScanError::new_str(
*mark, *mark,
"while scanning a YAML directive, found extremely long version number", "while scanning a YAML directive, found extremely long version number",
)); ));
@ -1075,7 +1081,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
if length == 0 { if length == 0 {
return Err(ScanError::new( return Err(ScanError::new_str(
*mark, *mark,
"while scanning a YAML directive, did not find expected version number", "while scanning a YAML directive, did not find expected version number",
)); ));
@ -1103,7 +1109,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
if is_blank_or_breakz(self.ch()) { if is_blank_or_breakz(self.ch()) {
Ok(Token(*mark, TokenType::TagDirective(handle, prefix))) Ok(Token(*mark, TokenType::TagDirective(handle, prefix)))
} else { } else {
Err(ScanError::new( Err(ScanError::new_str(
*mark, *mark,
"while scanning TAG, did not find expected whitespace or line break", "while scanning TAG, did not find expected whitespace or line break",
)) ))
@ -1154,7 +1160,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
// XXX: ex 7.2, an empty scalar can follow a secondary tag // XXX: ex 7.2, an empty scalar can follow a secondary tag
Ok(Token(start_mark, TokenType::Tag(handle, suffix))) Ok(Token(start_mark, TokenType::Tag(handle, suffix)))
} else { } else {
Err(ScanError::new( Err(ScanError::new_str(
start_mark, start_mark,
"while scanning a tag, did not find expected whitespace or line break", "while scanning a tag, did not find expected whitespace or line break",
)) ))
@ -1164,7 +1170,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
fn scan_tag_handle(&mut self, directive: bool, mark: &Marker) -> Result<String, ScanError> { fn scan_tag_handle(&mut self, directive: bool, mark: &Marker) -> Result<String, ScanError> {
let mut string = String::new(); let mut string = String::new();
if self.look_ch() != '!' { if self.look_ch() != '!' {
return Err(ScanError::new( return Err(ScanError::new_str(
*mark, *mark,
"while scanning a tag, did not find expected '!'", "while scanning a tag, did not find expected '!'",
)); ));
@ -1186,7 +1192,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
// It's either the '!' tag or not really a tag handle. If it's a %TAG // It's either the '!' tag or not really a tag handle. If it's a %TAG
// directive, it's an error. If it's a tag token, it must be a part of // directive, it's an error. If it's a tag token, it must be a part of
// URI. // URI.
return Err(ScanError::new( return Err(ScanError::new_str(
*mark, *mark,
"while parsing a tag directive, did not find expected '!'", "while parsing a tag directive, did not find expected '!'",
)); ));
@ -1208,7 +1214,10 @@ impl<T: Iterator<Item = char>> Scanner<T> {
self.skip_non_blank(); self.skip_non_blank();
} else if !is_tag_char(self.ch()) { } else if !is_tag_char(self.ch()) {
// Otherwise, check if the first global tag character is valid. // Otherwise, check if the first global tag character is valid.
return Err(ScanError::new(*start_mark, "invalid global tag character")); return Err(ScanError::new_str(
*start_mark,
"invalid global tag character",
));
} else if self.ch() == '%' { } else if self.ch() == '%' {
// If it is valid and an escape sequence, escape it. // If it is valid and an escape sequence, escape it.
string.push(self.scan_uri_escapes(start_mark)?); string.push(self.scan_uri_escapes(start_mark)?);
@ -1249,7 +1258,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
if self.ch() != '>' { if self.ch() != '>' {
return Err(ScanError::new( return Err(ScanError::new_str(
*start_mark, *start_mark,
"while scanning a verbatim tag, did not find the expected '>'", "while scanning a verbatim tag, did not find the expected '>'",
)); ));
@ -1288,7 +1297,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
if length == 0 { if length == 0 {
return Err(ScanError::new( return Err(ScanError::new_str(
*mark, *mark,
"while parsing a tag, did not find expected tag URI", "while parsing a tag, did not find expected tag URI",
)); ));
@ -1304,7 +1313,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
self.lookahead(3); self.lookahead(3);
if !(self.ch() == '%' && is_hex(self.buffer[1]) && is_hex(self.buffer[2])) { if !(self.ch() == '%' && is_hex(self.buffer[1]) && is_hex(self.buffer[2])) {
return Err(ScanError::new( return Err(ScanError::new_str(
*mark, *mark,
"while parsing a tag, did not find URI escaped octet", "while parsing a tag, did not find URI escaped octet",
)); ));
@ -1318,7 +1327,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
_ if octet & 0xF0 == 0xE0 => 3, _ if octet & 0xF0 == 0xE0 => 3,
_ if octet & 0xF8 == 0xF0 => 4, _ if octet & 0xF8 == 0xF0 => 4,
_ => { _ => {
return Err(ScanError::new( return Err(ScanError::new_str(
*mark, *mark,
"while parsing a tag, found an incorrect leading UTF-8 octet", "while parsing a tag, found an incorrect leading UTF-8 octet",
)); ));
@ -1327,7 +1336,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
code = octet; code = octet;
} else { } else {
if octet & 0xc0 != 0x80 { if octet & 0xc0 != 0x80 {
return Err(ScanError::new( return Err(ScanError::new_str(
*mark, *mark,
"while parsing a tag, found an incorrect trailing UTF-8 octet", "while parsing a tag, found an incorrect trailing UTF-8 octet",
)); ));
@ -1345,7 +1354,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
match char::from_u32(code) { match char::from_u32(code) {
Some(ch) => Ok(ch), Some(ch) => Ok(ch),
None => Err(ScanError::new( None => Err(ScanError::new_str(
*mark, *mark,
"while parsing a tag, found an invalid UTF-8 codepoint", "while parsing a tag, found an invalid UTF-8 codepoint",
)), )),
@ -1374,7 +1383,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
if string.is_empty() { if string.is_empty() {
return Err(ScanError::new(start_mark, "while scanning an anchor or alias, did not find expected alphabetic or numeric character")); return Err(ScanError::new_str(start_mark, "while scanning an anchor or alias, did not find expected alphabetic or numeric character"));
} }
if alias { if alias {
@ -1452,7 +1461,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
self.flow_level = self self.flow_level = self
.flow_level .flow_level
.checked_add(1) .checked_add(1)
.ok_or_else(|| ScanError::new(self.mark, "recursion limit exceeded"))?; .ok_or_else(|| ScanError::new_str(self.mark, "recursion limit exceeded"))?;
Ok(()) Ok(())
} }
@ -1471,14 +1480,14 @@ impl<T: Iterator<Item = char>> Scanner<T> {
fn fetch_block_entry(&mut self) -> ScanResult { fn fetch_block_entry(&mut self) -> ScanResult {
if self.flow_level > 0 { if self.flow_level > 0 {
// - * only allowed in block // - * only allowed in block
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
r#""-" is only valid inside a block"#, r#""-" is only valid inside a block"#,
)); ));
} }
// Check if we are allowed to start a new entry. // Check if we are allowed to start a new entry.
if !self.simple_key_allowed { if !self.simple_key_allowed {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"block sequence entries are not allowed in this context", "block sequence entries are not allowed in this context",
)); ));
@ -1487,7 +1496,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
// ???, fixes test G9HC. // ???, fixes test G9HC.
if let Some(Token(mark, TokenType::Anchor(..) | TokenType::Tag(..))) = self.tokens.back() { if let Some(Token(mark, TokenType::Anchor(..) | TokenType::Tag(..))) = self.tokens.back() {
if self.mark.col == 0 && mark.col == 0 && self.indent > -1 { if self.mark.col == 0 && mark.col == 0 && self.indent > -1 {
return Err(ScanError::new(*mark, "invalid indentation for anchor")); return Err(ScanError::new_str(*mark, "invalid indentation for anchor"));
} }
} }
@ -1500,7 +1509,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
let found_tabs = self.skip_ws_to_eol(SkipTabs::Yes)?.found_tabs(); let found_tabs = self.skip_ws_to_eol(SkipTabs::Yes)?.found_tabs();
self.lookahead(2); self.lookahead(2);
if found_tabs && self.buffer[0] == '-' && is_blank_or_breakz(self.buffer[1]) { if found_tabs && self.buffer[0] == '-' && is_blank_or_breakz(self.buffer[1]) {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"'-' must be followed by a valid YAML whitespace", "'-' must be followed by a valid YAML whitespace",
)); ));
@ -1574,7 +1583,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
self.skip_non_blank(); self.skip_non_blank();
if is_digit(self.look_ch()) { if is_digit(self.look_ch()) {
if self.ch() == '0' { if self.ch() == '0' {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"while scanning a block scalar, found an indentation indicator equal to 0", "while scanning a block scalar, found an indentation indicator equal to 0",
)); ));
@ -1584,7 +1593,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
} else if is_digit(self.ch()) { } else if is_digit(self.ch()) {
if self.ch() == '0' { if self.ch() == '0' {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"while scanning a block scalar, found an indentation indicator equal to 0", "while scanning a block scalar, found an indentation indicator equal to 0",
)); ));
@ -1607,7 +1616,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
// Check if we are at the end of the line. // Check if we are at the end of the line.
if !is_breakz(self.look_ch()) { if !is_breakz(self.look_ch()) {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"while scanning a block scalar, did not find expected comment or line break", "while scanning a block scalar, did not find expected comment or line break",
)); ));
@ -1619,7 +1628,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
if self.look_ch() == '\t' { if self.look_ch() == '\t' {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"a block scalar content cannot start with a tab", "a block scalar content cannot start with a tab",
)); ));
@ -1663,7 +1672,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
if self.mark.col < indent && (self.mark.col as isize) > self.indent { if self.mark.col < indent && (self.mark.col as isize) > self.indent {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"wrongly indented line in block scalar", "wrongly indented line in block scalar",
)); ));
@ -1891,21 +1900,21 @@ impl<T: Iterator<Item = char>> Scanner<T> {
&& (self.buffer[2] == '.'))) && (self.buffer[2] == '.')))
&& is_blank_or_breakz(self.buffer[3]) && is_blank_or_breakz(self.buffer[3])
{ {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"while scanning a quoted scalar, found unexpected document indicator", "while scanning a quoted scalar, found unexpected document indicator",
)); ));
} }
if is_z(self.ch()) { if is_z(self.ch()) {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"while scanning a quoted scalar, found unexpected end of stream", "while scanning a quoted scalar, found unexpected end of stream",
)); ));
} }
if (self.mark.col as isize) < self.indent { if (self.mark.col as isize) < self.indent {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"invalid indentation in quoted scalar", "invalid indentation in quoted scalar",
)); ));
@ -1931,7 +1940,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
// Consume a space or a tab character. // Consume a space or a tab character.
if leading_blanks { if leading_blanks {
if self.ch() == '\t' && (self.mark.col as isize) < self.indent { if self.ch() == '\t' && (self.mark.col as isize) < self.indent {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"tab cannot be used as indentation", "tab cannot be used as indentation",
)); ));
@ -1992,7 +2001,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
// Inside a flow context, this is allowed. // Inside a flow context, this is allowed.
':' if self.flow_level > 0 => {} ':' if self.flow_level > 0 => {}
_ => { _ => {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"invalid trailing content after double-quoted scalar", "invalid trailing content after double-quoted scalar",
)); ));
@ -2094,7 +2103,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
'u' => code_length = 4, 'u' => code_length = 4,
'U' => code_length = 8, 'U' => code_length = 8,
_ => { _ => {
return Err(ScanError::new( return Err(ScanError::new_str(
*start_mark, *start_mark,
"while parsing a quoted scalar, found unknown escape character", "while parsing a quoted scalar, found unknown escape character",
)) ))
@ -2108,7 +2117,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
let mut value = 0u32; let mut value = 0u32;
for i in 0..code_length { for i in 0..code_length {
if !is_hex(self.buffer[i]) { if !is_hex(self.buffer[i]) {
return Err(ScanError::new( return Err(ScanError::new_str(
*start_mark, *start_mark,
"while parsing a quoted scalar, did not find expected hexadecimal number", "while parsing a quoted scalar, did not find expected hexadecimal number",
)); ));
@ -2117,7 +2126,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
let Some(ch) = char::from_u32(value) else { let Some(ch) = char::from_u32(value) else {
return Err(ScanError::new( return Err(ScanError::new_str(
*start_mark, *start_mark,
"while parsing a quoted scalar, found invalid Unicode character escape code", "while parsing a quoted scalar, found invalid Unicode character escape code",
)); ));
@ -2150,7 +2159,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
let start_mark = self.mark; let start_mark = self.mark;
if self.flow_level > 0 && (start_mark.col as isize) < indent { if self.flow_level > 0 && (start_mark.col as isize) < indent {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"invalid indentation in flow construct", "invalid indentation in flow construct",
)); ));
@ -2168,7 +2177,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
} }
if self.flow_level > 0 && self.ch() == '-' && is_flow(self.buffer[1]) { if self.flow_level > 0 && self.ch() == '-' && is_flow(self.buffer[1]) {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"plain scalar cannot start with '-' followed by ,[]{}", "plain scalar cannot start with '-' followed by ,[]{}",
)); ));
@ -2232,7 +2241,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
// empty. Skip to the end of the line. // empty. Skip to the end of the line.
self.skip_ws_to_eol(SkipTabs::Yes)?; self.skip_ws_to_eol(SkipTabs::Yes)?;
if !is_breakz(self.ch()) { if !is_breakz(self.ch()) {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"while scanning a plain scalar, found a tab", "while scanning a plain scalar, found a tab",
)); ));
@ -2274,7 +2283,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
if self.flow_level == 0 { if self.flow_level == 0 {
// Check if we are allowed to start a new key (not necessarily simple). // Check if we are allowed to start a new key (not necessarily simple).
if !self.simple_key_allowed { if !self.simple_key_allowed {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"mapping keys are not allowed in this context", "mapping keys are not allowed in this context",
)); ));
@ -2301,7 +2310,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
self.skip_non_blank(); self.skip_non_blank();
self.skip_yaml_whitespace()?; self.skip_yaml_whitespace()?;
if self.ch() == '\t' { if self.ch() == '\t' {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark(), self.mark(),
"tabs disallowed in this context", "tabs disallowed in this context",
)); ));
@ -2322,7 +2331,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
&& !self.skip_ws_to_eol(SkipTabs::Yes)?.has_valid_yaml_ws() && !self.skip_ws_to_eol(SkipTabs::Yes)?.has_valid_yaml_ws()
&& (self.ch() == '-' || is_alpha(self.ch())) && (self.ch() == '-' || is_alpha(self.ch()))
{ {
return Err(ScanError::new( return Err(ScanError::new_str(
self.mark, self.mark,
"':' must be followed by a valid YAML whitespace", "':' must be followed by a valid YAML whitespace",
)); ));
@ -2334,7 +2343,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
self.insert_token(sk.token_number - self.tokens_parsed, tok); self.insert_token(sk.token_number - self.tokens_parsed, tok);
if self.implicit_flow_mapping { if self.implicit_flow_mapping {
if sk.mark.line < start_mark.line { if sk.mark.line < start_mark.line {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"illegal placement of ':' indicator", "illegal placement of ':' indicator",
)); ));
@ -2364,7 +2373,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
// The ':' indicator follows a complex key. // The ':' indicator follows a complex key.
if self.flow_level == 0 { if self.flow_level == 0 {
if !self.simple_key_allowed { if !self.simple_key_allowed {
return Err(ScanError::new( return Err(ScanError::new_str(
start_mark, start_mark,
"mapping values are not allowed in this context", "mapping values are not allowed in this context",
)); ));
@ -2489,7 +2498,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
fn remove_simple_key(&mut self) -> ScanResult { fn remove_simple_key(&mut self) -> ScanResult {
let last = self.simple_keys.last_mut().unwrap(); let last = self.simple_keys.last_mut().unwrap();
if last.possible && last.required { if last.possible && last.required {
return Err(ScanError::new(self.mark, "simple key expected")); return Err(ScanError::new_str(self.mark, "simple key expected"));
} }
last.possible = false; last.possible = false;