diff --git a/saphyr/examples/dump_yaml.rs b/saphyr/examples/dump_yaml.rs index 8fce0f3..3455a9a 100644 --- a/saphyr/examples/dump_yaml.rs +++ b/saphyr/examples/dump_yaml.rs @@ -21,13 +21,13 @@ fn dump_node(doc: &yaml::Yaml, indent: usize) { yaml::Yaml::Hash(ref h) => { for (k, v) in h { print_indent(indent); - println!("{:?}:", k); + println!("{k:?}:"); dump_node(v, indent + 1); } } _ => { print_indent(indent); - println!("{:?}", doc); + println!("{doc:?}"); } } } diff --git a/saphyr/src/emitter.rs b/saphyr/src/emitter.rs index f20a3ed..bf1bbaa 100644 --- a/saphyr/src/emitter.rs +++ b/saphyr/src/emitter.rs @@ -1,7 +1,7 @@ +use crate::yaml::{Hash, Yaml}; use std::convert::From; use std::error::Error; use std::fmt::{self, Display}; -use crate::yaml::{Hash, Yaml}; #[derive(Copy, Clone, Debug)] pub enum EmitError { @@ -30,6 +30,7 @@ impl From for EmitError { } } +#[allow(clippy::module_name_repetitions)] pub struct YamlEmitter<'a> { writer: &'a mut dyn fmt::Write, best_indent: usize, @@ -126,6 +127,7 @@ impl<'a> YamlEmitter<'a> { } /// Determine if this emitter is using 'compact inline notation'. + #[must_use] pub fn is_compact(&self) -> bool { self.compact } @@ -157,7 +159,7 @@ impl<'a> YamlEmitter<'a> { if need_quotes(v) { escape_str(self.writer, v)?; } else { - write!(self.writer, "{}", v)?; + write!(self.writer, "{v}")?; } Ok(()) } @@ -170,11 +172,11 @@ impl<'a> YamlEmitter<'a> { Ok(()) } Yaml::Integer(v) => { - write!(self.writer, "{}", v)?; + write!(self.writer, "{v}")?; Ok(()) } Yaml::Real(ref v) => { - write!(self.writer, "{}", v)?; + write!(self.writer, "{v}")?; Ok(()) } Yaml::Null | Yaml::BadValue => { @@ -182,7 +184,7 @@ impl<'a> YamlEmitter<'a> { Ok(()) } // XXX(chenyh) Alias - _ => Ok(()), + Yaml::Alias(_) => Ok(()), } } @@ -210,10 +212,7 @@ impl<'a> YamlEmitter<'a> { } else { self.level += 1; for (cnt, (k, v)) in h.iter().enumerate() { - let complex_key = match *k { - Yaml::Hash(_) | Yaml::Array(_) => true, - _ => false, - }; + let complex_key = matches!(*k, Yaml::Hash(_) | Yaml::Array(_)); if cnt > 0 { writeln!(self.writer)?; self.write_indent()?; @@ -286,19 +285,22 @@ impl<'a> YamlEmitter<'a> { /// * When the string is null or ~ (otherwise, it would be considered as a null value); /// * When the string looks like a number, such as integers (e.g. 2, 14, etc.), floats (e.g. 2.6, 14.9) and exponential numbers (e.g. 12e7, etc.) (otherwise, it would be treated as a numeric value); /// * When the string looks like a date (e.g. 2014-12-31) (otherwise it would be automatically converted into a Unix timestamp). +#[allow(clippy::doc_markdown)] fn need_quotes(string: &str) -> bool { fn need_quotes_spaces(string: &str) -> bool { string.starts_with(' ') || string.ends_with(' ') } - string == "" + string.is_empty() || need_quotes_spaces(string) - || string.starts_with(|character: char| match character { - '&' | '*' | '?' | '|' | '-' | '<' | '>' | '=' | '!' | '%' | '@' => true, - _ => false, + || string.starts_with(|character: char| { + matches!( + character, + '&' | '*' | '?' | '|' | '-' | '<' | '>' | '=' | '!' | '%' | '@' + ) }) - || string.contains(|character: char| match character { - ':' + || string.contains(|character: char| { + matches!(character, ':' | '{' | '}' | '[' @@ -314,8 +316,7 @@ fn need_quotes(string: &str) -> bool { | '\n' | '\r' | '\x0e'..='\x1a' - | '\x1c'..='\x1f' => true, - _ => false, + | '\x1c'..='\x1f') }) || [ // http://yaml.org/type/bool.html @@ -335,6 +336,7 @@ fn need_quotes(string: &str) -> bool { } #[cfg(test)] +#[allow(clippy::similar_names)] mod test { use super::*; use crate::YamlLoader; @@ -354,18 +356,18 @@ a4: - 2 "; - let docs = YamlLoader::load_from_str(&s).unwrap(); + let docs = YamlLoader::load_from_str(s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } - println!("original:\n{}", s); - println!("emitted:\n{}", writer); + println!("original:\n{s}"); + println!("emitted:\n{writer}"); let docs_new = match YamlLoader::load_from_str(&writer) { Ok(y) => y, - Err(e) => panic!(format!("{}", e)), + Err(e) => panic!("{}", e), }; let doc_new = &docs_new[0]; @@ -393,7 +395,7 @@ products: {}: empty hash key "#; - let docs = YamlLoader::load_from_str(&s).unwrap(); + let docs = YamlLoader::load_from_str(s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { @@ -402,7 +404,7 @@ products: } let docs_new = match YamlLoader::load_from_str(&writer) { Ok(y) => y, - Err(e) => panic!(format!("{}", e)), + Err(e) => panic!("{}", e), }; let doc_new = &docs_new[0]; assert_eq!(doc, doc_new); @@ -444,7 +446,7 @@ x: test y: avoid quoting here z: string with spaces"#; - let docs = YamlLoader::load_from_str(&s).unwrap(); + let docs = YamlLoader::load_from_str(s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { @@ -452,7 +454,7 @@ z: string with spaces"#; emitter.dump(doc).unwrap(); } - assert_eq!(s, writer, "actual:\n\n{}\n", writer); + assert_eq!(s, writer, "actual:\n\n{writer}\n"); } #[test] @@ -502,7 +504,7 @@ null0: ~ bool0: true bool1: false"#; - let docs = YamlLoader::load_from_str(&input).unwrap(); + let docs = YamlLoader::load_from_str(input).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { @@ -512,19 +514,18 @@ bool1: false"#; assert_eq!( expected, writer, - "expected:\n{}\nactual:\n{}\n", - expected, writer + "expected:\n{expected}\nactual:\n{writer}\n", ); } #[test] fn test_empty_and_nested() { - test_empty_and_nested_flag(false) + test_empty_and_nested_flag(false); } #[test] fn test_empty_and_nested_compact() { - test_empty_and_nested_flag(true) + test_empty_and_nested_flag(true); } fn test_empty_and_nested_flag(compact: bool) { @@ -551,7 +552,7 @@ e: h: []"# }; - let docs = YamlLoader::load_from_str(&s).unwrap(); + let docs = YamlLoader::load_from_str(s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { @@ -573,15 +574,15 @@ a: - - e - f"#; - let docs = YamlLoader::load_from_str(&s).unwrap(); + let docs = YamlLoader::load_from_str(s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } - println!("original:\n{}", s); - println!("emitted:\n{}", writer); + println!("original:\n{s}"); + println!("emitted:\n{writer}"); assert_eq!(s, writer); } @@ -597,15 +598,15 @@ a: - - f - - e"#; - let docs = YamlLoader::load_from_str(&s).unwrap(); + let docs = YamlLoader::load_from_str(s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } - println!("original:\n{}", s); - println!("emitted:\n{}", writer); + println!("original:\n{s}"); + println!("emitted:\n{writer}"); assert_eq!(s, writer); } @@ -619,17 +620,16 @@ a: d: e: f"#; - let docs = YamlLoader::load_from_str(&s).unwrap(); + let docs = YamlLoader::load_from_str(s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } - println!("original:\n{}", s); - println!("emitted:\n{}", writer); + println!("original:\n{s}"); + println!("emitted:\n{writer}"); assert_eq!(s, writer); } - } diff --git a/saphyr/src/lib.rs b/saphyr/src/lib.rs index ae95e0f..ee432ca 100644 --- a/saphyr/src/lib.rs +++ b/saphyr/src/lib.rs @@ -37,11 +37,16 @@ //! ``` #![doc(html_root_url = "https://docs.rs/yaml-rust/0.4.5")] -#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] -#![cfg_attr(feature = "cargo-clippy", warn(cyclomatic_complexity))] +#![cfg_attr(feature = "cargo-clippy", warn(clippy::pedantic))] #![cfg_attr( feature = "cargo-clippy", - allow(match_same_arms, should_implement_trait) + allow( + clippy::match_same_arms, + clippy::should_implement_trait, + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::redundant_else, + ) )] extern crate linked_hash_map; @@ -117,5 +122,4 @@ key1:a2 assert!(YamlLoader::load_from_str(s).is_err()); assert!(try_fail(s).is_err()); } - } diff --git a/saphyr/src/parser.rs b/saphyr/src/parser.rs index 4a63146..90539f1 100644 --- a/saphyr/src/parser.rs +++ b/saphyr/src/parser.rs @@ -1,4 +1,4 @@ -use crate::scanner::*; +use crate::scanner::{Marker, ScanError, Scanner, TScalarStyle, Token, TokenType}; use std::collections::HashMap; #[derive(Clone, Copy, PartialEq, Debug, Eq)] @@ -58,11 +58,12 @@ impl Event { } fn empty_scalar_with_anchor(anchor: usize, tag: Option) -> Event { - Event::Scalar("".to_owned(), TScalarStyle::Plain, anchor, tag) + Event::Scalar(String::new(), TScalarStyle::Plain, anchor, tag) } } #[derive(Debug)] +#[allow(dead_code)] pub struct Parser { scanner: Scanner, states: Vec, @@ -84,7 +85,7 @@ pub trait MarkedEventReceiver { impl MarkedEventReceiver for R { fn on_event(&mut self, ev: Event, _mark: Marker) { - self.on_event(ev) + self.on_event(ev); } } @@ -107,12 +108,11 @@ impl> Parser { } pub fn peek(&mut self) -> Result<&(Event, Marker), ScanError> { - match self.current { - Some(ref x) => Ok(x), - None => { - self.current = Some(self.next()?); - self.peek() - } + if let Some(ref x) = self.current { + Ok(x) + } else { + self.current = Some(self.next()?); + self.peek() } } @@ -155,7 +155,7 @@ impl> Parser { //self.peek_token(); } fn pop_state(&mut self) { - self.state = self.states.pop().unwrap() + self.state = self.states.pop().unwrap(); } fn push_state(&mut self, state: State) { self.states.push(state); @@ -242,7 +242,7 @@ impl> Parser { self.load_mapping(recv) } _ => { - println!("UNREACHABLE EVENT: {:?}", first_ev); + println!("UNREACHABLE EVENT: {first_ev:?}"); unreachable!(); } } @@ -345,9 +345,12 @@ impl> Parser { self.skip(); Ok((Event::StreamEnd, mark)) } - Token(_, TokenType::VersionDirective(..)) - | Token(_, TokenType::TagDirective(..)) - | Token(_, TokenType::DocumentStart) => { + Token( + _, + TokenType::VersionDirective(..) + | TokenType::TagDirective(..) + | TokenType::DocumentStart, + ) => { // explicit document self._explicit_document_start() } @@ -403,11 +406,14 @@ impl> Parser { fn document_content(&mut self) -> ParseResult { match *self.peek_token()? { - Token(mark, TokenType::VersionDirective(..)) - | Token(mark, TokenType::TagDirective(..)) - | Token(mark, TokenType::DocumentStart) - | Token(mark, TokenType::DocumentEnd) - | Token(mark, TokenType::StreamEnd) => { + Token( + mark, + TokenType::VersionDirective(..) + | TokenType::TagDirective(..) + | TokenType::DocumentStart + | TokenType::DocumentEnd + | TokenType::StreamEnd, + ) => { self.pop_state(); // empty scalar Ok((Event::empty_scalar(), mark)) @@ -417,11 +423,9 @@ impl> Parser { } fn document_end(&mut self) -> ParseResult { - let mut _implicit = true; let marker: Marker = match *self.peek_token()? { Token(mark, TokenType::DocumentEnd) => { self.skip(); - _implicit = false; mark } Token(mark, _) => mark, @@ -432,7 +436,7 @@ impl> Parser { Ok((Event::DocumentEnd, marker)) } - fn register_anchor(&mut self, name: String, _: &Marker) -> Result { + fn register_anchor(&mut self, name: String, _: &Marker) -> usize { // anchors can be overridden/reused // if self.anchors.contains_key(name) { // return Err(ScanError::new(*mark, @@ -441,7 +445,7 @@ impl> Parser { let new_id = self.anchor_id; self.anchor_id += 1; self.anchors.insert(name, new_id); - Ok(new_id) + new_id } fn parse_node(&mut self, block: bool, indentless_sequence: bool) -> ParseResult { @@ -466,7 +470,7 @@ impl> Parser { } Token(_, TokenType::Anchor(_)) => { if let Token(mark, TokenType::Anchor(name)) = self.fetch_token() { - anchor_id = self.register_anchor(name, &mark)?; + anchor_id = self.register_anchor(name, &mark); if let TokenType::Tag(..) = self.peek_token()?.1 { if let tg @ TokenType::Tag(..) = self.fetch_token().1 { tag = Some(tg); @@ -483,7 +487,7 @@ impl> Parser { tag = Some(tg); if let TokenType::Anchor(_) = self.peek_token()?.1 { if let Token(mark, TokenType::Anchor(name)) = self.fetch_token() { - anchor_id = self.register_anchor(name, &mark)?; + anchor_id = self.register_anchor(name, &mark); } else { unreachable!() } @@ -545,18 +549,15 @@ impl> Parser { match *self.peek_token()? { Token(_, TokenType::Key) => { self.skip(); - match *self.peek_token()? { - Token(mark, TokenType::Key) - | Token(mark, TokenType::Value) - | Token(mark, TokenType::BlockEnd) => { - self.state = State::BlockMappingValue; - // empty scalar - Ok((Event::empty_scalar(), mark)) - } - _ => { - self.push_state(State::BlockMappingValue); - self.parse_node(true, true) - } + if let Token(mark, TokenType::Key | TokenType::Value | TokenType::BlockEnd) = + *self.peek_token()? + { + self.state = State::BlockMappingValue; + // empty scalar + Ok((Event::empty_scalar(), mark)) + } else { + self.push_state(State::BlockMappingValue); + self.parse_node(true, true) } } // XXX(chenyh): libyaml failed to parse spec 1.2, ex8.18 @@ -580,18 +581,15 @@ impl> Parser { match *self.peek_token()? { Token(_, TokenType::Value) => { self.skip(); - match *self.peek_token()? { - Token(mark, TokenType::Key) - | Token(mark, TokenType::Value) - | Token(mark, TokenType::BlockEnd) => { - self.state = State::BlockMappingKey; - // empty scalar - Ok((Event::empty_scalar(), mark)) - } - _ => { - self.push_state(State::BlockMappingKey); - self.parse_node(true, true) - } + if let Token(mark, TokenType::Key | TokenType::Value | TokenType::BlockEnd) = + *self.peek_token()? + { + self.state = State::BlockMappingKey; + // empty scalar + Ok((Event::empty_scalar(), mark)) + } else { + self.push_state(State::BlockMappingKey); + self.parse_node(true, true) } } Token(mark, _) => { @@ -607,50 +605,50 @@ impl> Parser { let _ = self.peek_token()?; self.skip(); } - let marker: Marker = - { - match *self.peek_token()? { - Token(mark, TokenType::FlowMappingEnd) => mark, - Token(mark, _) => { - if !first { - match *self.peek_token()? { - Token(_, TokenType::FlowEntry) => self.skip(), - Token(mark, _) => return Err(ScanError::new(mark, - "while parsing a flow mapping, did not find expected ',' or '}'")) - } - } - + let marker: Marker = { + match *self.peek_token()? { + Token(mark, TokenType::FlowMappingEnd) => mark, + Token(mark, _) => { + if !first { match *self.peek_token()? { - Token(_, TokenType::Key) => { - self.skip(); - match *self.peek_token()? { - Token(mark, TokenType::Value) - | Token(mark, TokenType::FlowEntry) - | Token(mark, TokenType::FlowMappingEnd) => { - self.state = State::FlowMappingValue; - return Ok((Event::empty_scalar(), mark)); - } - _ => { - self.push_state(State::FlowMappingValue); - return self.parse_node(false, false); - } - } - } - Token(marker, TokenType::Value) => { + Token(_, TokenType::FlowEntry) => self.skip(), + Token(mark, _) => return Err(ScanError::new( + mark, + "while parsing a flow mapping, did not find expected ',' or '}'", + )), + } + } + + match *self.peek_token()? { + Token(_, TokenType::Key) => { + self.skip(); + if let Token( + mark, + TokenType::Value | TokenType::FlowEntry | TokenType::FlowMappingEnd, + ) = *self.peek_token()? + { self.state = State::FlowMappingValue; - return Ok((Event::empty_scalar(), marker)); - } - Token(_, TokenType::FlowMappingEnd) => (), - _ => { - self.push_state(State::FlowMappingEmptyValue); + return Ok((Event::empty_scalar(), mark)); + } else { + self.push_state(State::FlowMappingValue); return self.parse_node(false, false); } } - - mark + Token(marker, TokenType::Value) => { + self.state = State::FlowMappingValue; + return Ok((Event::empty_scalar(), marker)); + } + Token(_, TokenType::FlowMappingEnd) => (), + _ => { + self.push_state(State::FlowMappingEmptyValue); + return self.parse_node(false, false); + } } + + mark } - }; + } + }; self.pop_state(); self.skip(); @@ -736,18 +734,16 @@ impl> Parser { } } self.skip(); - match *self.peek_token()? { - Token(mark, TokenType::BlockEntry) - | Token(mark, TokenType::Key) - | Token(mark, TokenType::Value) - | Token(mark, TokenType::BlockEnd) => { - self.state = State::IndentlessSequenceEntry; - Ok((Event::empty_scalar(), mark)) - } - _ => { - self.push_state(State::IndentlessSequenceEntry); - self.parse_node(true, false) - } + if let Token( + mark, + TokenType::BlockEntry | TokenType::Key | TokenType::Value | TokenType::BlockEnd, + ) = *self.peek_token()? + { + self.state = State::IndentlessSequenceEntry; + Ok((Event::empty_scalar(), mark)) + } else { + self.push_state(State::IndentlessSequenceEntry); + self.parse_node(true, false) } } @@ -766,15 +762,14 @@ impl> Parser { } Token(_, TokenType::BlockEntry) => { self.skip(); - match *self.peek_token()? { - Token(mark, TokenType::BlockEntry) | Token(mark, TokenType::BlockEnd) => { - self.state = State::BlockSequenceEntry; - Ok((Event::empty_scalar(), mark)) - } - _ => { - self.push_state(State::BlockSequenceEntry); - self.parse_node(true, false) - } + if let Token(mark, TokenType::BlockEntry | TokenType::BlockEnd) = + *self.peek_token()? + { + self.state = State::BlockSequenceEntry; + Ok((Event::empty_scalar(), mark)) + } else { + self.push_state(State::BlockSequenceEntry); + self.parse_node(true, false) } } Token(mark, _) => Err(ScanError::new( @@ -785,18 +780,15 @@ impl> Parser { } fn flow_sequence_entry_mapping_key(&mut self) -> ParseResult { - match *self.peek_token()? { - Token(mark, TokenType::Value) - | Token(mark, TokenType::FlowEntry) - | Token(mark, TokenType::FlowSequenceEnd) => { - self.skip(); - self.state = State::FlowSequenceEntryMappingValue; - Ok((Event::empty_scalar(), mark)) - } - _ => { - self.push_state(State::FlowSequenceEntryMappingValue); - self.parse_node(false, false) - } + if let Token(mark, TokenType::Value | TokenType::FlowEntry | TokenType::FlowSequenceEnd) = + *self.peek_token()? + { + self.skip(); + self.state = State::FlowSequenceEntryMappingValue; + Ok((Event::empty_scalar(), mark)) + } else { + self.push_state(State::FlowSequenceEntryMappingValue); + self.parse_node(false, false) } } @@ -805,15 +797,14 @@ impl> Parser { Token(_, TokenType::Value) => { self.skip(); self.state = State::FlowSequenceEntryMappingValue; - match *self.peek_token()? { - Token(mark, TokenType::FlowEntry) | Token(mark, TokenType::FlowSequenceEnd) => { - self.state = State::FlowSequenceEntryMappingEnd; - Ok((Event::empty_scalar(), mark)) - } - _ => { - self.push_state(State::FlowSequenceEntryMappingEnd); - self.parse_node(false, false) - } + if let Token(mark, TokenType::FlowEntry | TokenType::FlowSequenceEnd) = + *self.peek_token()? + { + self.state = State::FlowSequenceEntryMappingEnd; + Ok((Event::empty_scalar(), mark)) + } else { + self.push_state(State::FlowSequenceEntryMappingEnd); + self.parse_node(false, false) } } Token(mark, _) => { @@ -823,6 +814,7 @@ impl> Parser { } } + #[allow(clippy::unnecessary_wraps)] fn flow_sequence_entry_mapping_end(&mut self) -> ParseResult { self.state = State::FlowSequenceEntry; Ok((Event::MappingEnd, self.scanner.mark())) diff --git a/saphyr/src/scanner.rs b/saphyr/src/scanner.rs index a8659a8..c352df8 100644 --- a/saphyr/src/scanner.rs +++ b/saphyr/src/scanner.rs @@ -1,3 +1,6 @@ +#![allow(clippy::cast_possible_wrap)] +#![allow(clippy::cast_sign_loss)] + use std::collections::VecDeque; use std::error::Error; use std::{char, fmt}; @@ -30,14 +33,17 @@ impl Marker { Marker { index, line, col } } + #[must_use] pub fn index(&self) -> usize { self.index } + #[must_use] pub fn line(&self) -> usize { self.line } + #[must_use] pub fn col(&self) -> usize { self.col } @@ -50,6 +56,7 @@ pub struct ScanError { } impl ScanError { + #[must_use] pub fn new(loc: Marker, info: &str) -> ScanError { ScanError { mark: loc, @@ -57,6 +64,7 @@ impl ScanError { } } + #[must_use] pub fn marker(&self) -> &Marker { &self.mark } @@ -137,6 +145,7 @@ impl SimpleKey { } #[derive(Debug)] +#[allow(clippy::struct_excessive_bools)] pub struct Scanner { rdr: T, mark: Marker, @@ -194,19 +203,15 @@ fn is_blankz(c: char) -> bool { } #[inline] fn is_digit(c: char) -> bool { - c >= '0' && c <= '9' + c.is_ascii_digit() } #[inline] fn is_alpha(c: char) -> bool { - match c { - '0'..='9' | 'a'..='z' | 'A'..='Z' => true, - '_' | '-' => true, - _ => false, - } + matches!(c, '0'..='9' | 'a'..='z' | 'A'..='Z' | '_' | '-') } #[inline] fn is_hex(c: char) -> bool { - (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') + c.is_ascii_digit() || ('a'..='f').contains(&c) || ('A'..='F').contains(&c) } #[inline] fn as_hex(c: char) -> u32 { @@ -219,10 +224,7 @@ fn as_hex(c: char) -> u32 { } #[inline] fn is_flow(c: char) -> bool { - match c { - ',' | '[' | ']' | '{' | '}' => true, - _ => false, - } + matches!(c, ',' | '[' | ']' | '{' | '}') } pub type ScanResult = Result<(), ScanError>; @@ -251,10 +253,7 @@ impl> Scanner { } #[inline] pub fn get_error(&self) -> Option { - match self.error { - None => None, - Some(ref e) => Some(e.clone()), - } + self.error.as_ref().map(std::clone::Clone::clone) } #[inline] @@ -419,7 +418,7 @@ impl> Scanner { ':' | '?' if !is_blankz(nc) && self.flow_level == 0 => self.fetch_plain_scalar(), '%' | '@' | '`' => Err(ScanError::new( self.mark, - &format!("unexpected character: `{}'", c), + &format!("unexpected character: `{c}'"), )), _ => self.fetch_plain_scalar(), } @@ -697,7 +696,7 @@ impl> Scanner { } let is_secondary = handle == "!!"; - let prefix = self.scan_tag_uri(true, is_secondary, &String::new(), mark)?; + let prefix = self.scan_tag_uri(true, is_secondary, "", mark)?; self.lookahead(1); @@ -733,7 +732,7 @@ impl> Scanner { // Eat '!<' self.skip(); self.skip(); - suffix = self.scan_tag_uri(false, false, &String::new(), &start_mark)?; + suffix = self.scan_tag_uri(false, false, "", &start_mark)?; if self.ch() != '>' { return Err(ScanError::new( @@ -751,7 +750,7 @@ impl> Scanner { if handle == "!!" { secondary = true; } - suffix = self.scan_tag_uri(false, secondary, &String::new(), &start_mark)?; + suffix = self.scan_tag_uri(false, secondary, "", &start_mark)?; } else { suffix = self.scan_tag_uri(false, false, &handle, &start_mark)?; handle = "!".to_owned(); @@ -1072,6 +1071,7 @@ impl> Scanner { Ok(()) } + #[allow(clippy::too_many_lines)] fn scan_block_scalar(&mut self, literal: bool) -> Result { let start_mark = self.mark; let mut chomping: i32 = 0; @@ -1280,6 +1280,7 @@ impl> Scanner { Ok(()) } + #[allow(clippy::too_many_lines)] fn scan_flow_scalar(&mut self, single: bool) -> Result { let start_mark = self.mark; @@ -1389,12 +1390,8 @@ impl> Scanner { value = (value << 4) + as_hex(self.buffer[i]); } - let ch = match char::from_u32(value) { - Some(v) => v, - None => { - return Err(ScanError::new(start_mark, - "while parsing a quoted scalar, found invalid Unicode character escape code")); - } + let Some(ch) = char::from_u32(value) else { + return Err(ScanError::new(start_mark, "while parsing a quoted scalar, found invalid Unicode character escape code")); }; string.push(ch); @@ -1739,6 +1736,7 @@ impl> Scanner { } #[cfg(test)] +#[allow(clippy::enum_glob_use)] mod test { use super::TokenType::*; use super::*; diff --git a/saphyr/src/yaml.rs b/saphyr/src/yaml.rs index 4bb70da..939cb58 100644 --- a/saphyr/src/yaml.rs +++ b/saphyr/src/yaml.rs @@ -1,6 +1,8 @@ -use linked_hash_map::LinkedHashMap; -use crate::parser::*; +#![allow(clippy::module_name_repetitions)] + +use crate::parser::{Event, MarkedEventReceiver, Parser}; use crate::scanner::{Marker, ScanError, TScalarStyle, TokenType}; +use linked_hash_map::LinkedHashMap; use std::collections::BTreeMap; use std::f64; use std::i64; @@ -201,6 +203,7 @@ impl YamlLoader { macro_rules! define_as ( ($name:ident, $t:ident, $yt:ident) => ( +#[must_use] pub fn $name(&self) -> Option<$t> { match *self { Yaml::$yt(v) => Some(v), @@ -212,6 +215,7 @@ pub fn $name(&self) -> Option<$t> { macro_rules! define_as_ref ( ($name:ident, $t:ty, $yt:ident) => ( +#[must_use] pub fn $name(&self) -> Option<$t> { match *self { Yaml::$yt(ref v) => Some(v), @@ -223,6 +227,7 @@ pub fn $name(&self) -> Option<$t> { macro_rules! define_into ( ($name:ident, $t:ty, $yt:ident) => ( +#[must_use] pub fn $name(self) -> Option<$t> { match self { Yaml::$yt(v) => Some(v), @@ -246,59 +251,58 @@ impl Yaml { define_into!(into_hash, Hash, Hash); define_into!(into_vec, Array, Array); + /// Returns the is null of this [`Yaml`]. + #[must_use] pub fn is_null(&self) -> bool { - match *self { - Yaml::Null => true, - _ => false, - } + matches!(*self, Yaml::Null) } + /// Returns the is badvalue of this [`Yaml`]. + #[must_use] pub fn is_badvalue(&self) -> bool { - match *self { - Yaml::BadValue => true, - _ => false, - } + matches!(*self, Yaml::BadValue) } + #[must_use] pub fn is_array(&self) -> bool { - match *self { - Yaml::Array(_) => true, - _ => false, - } + matches!(*self, Yaml::Array(_)) } + #[must_use] pub fn as_f64(&self) -> Option { - match *self { - Yaml::Real(ref v) => parse_f64(v), - _ => None, + if let Yaml::Real(ref v) = self { + parse_f64(v) + } else { + None } } + #[must_use] pub fn into_f64(self) -> Option { - match self { - Yaml::Real(ref v) => parse_f64(v), - _ => None, + if let Yaml::Real(ref v) = self { + parse_f64(v) + } else { + None } } } -#[cfg_attr(feature = "cargo-clippy", allow(should_implement_trait))] +#[cfg_attr(feature = "cargo-clippy", allow(clippy::should_implement_trait))] impl Yaml { // Not implementing FromStr because there is no possibility of Error. // This function falls back to Yaml::String if nothing else matches. + #[must_use] pub fn from_str(v: &str) -> Yaml { - if v.starts_with("0x") { - if let Ok(i) = i64::from_str_radix(&v[2..], 16) { + if let Some(number) = v.strip_prefix("0x") { + if let Ok(i) = i64::from_str_radix(number, 16) { return Yaml::Integer(i); } - } - if v.starts_with("0o") { - if let Ok(i) = i64::from_str_radix(&v[2..], 8) { + } else if let Some(number) = v.strip_prefix("0o") { + if let Ok(i) = i64::from_str_radix(number, 8) { return Yaml::Integer(i); } - } - if v.starts_with('+') { - if let Ok(i) = v[1..].parse::() { + } else if let Some(number) = v.strip_prefix('+') { + if let Ok(i) = number.parse::() { return Yaml::Integer(i); } } @@ -306,10 +310,15 @@ impl Yaml { "~" | "null" => Yaml::Null, "true" => Yaml::Boolean(true), "false" => Yaml::Boolean(false), - _ if v.parse::().is_ok() => Yaml::Integer(v.parse::().unwrap()), - // try parsing as f64 - _ if parse_f64(v).is_some() => Yaml::Real(v.to_owned()), - _ => Yaml::String(v.to_owned()), + _ => { + if let Ok(integer) = v.parse::() { + Yaml::Integer(integer) + } else if parse_f64(v).is_some() { + Yaml::Real(v.to_owned()) + } else { + Yaml::String(v.to_owned()) + } + } } } } @@ -348,7 +357,7 @@ impl IntoIterator for Yaml { fn into_iter(self) -> Self::IntoIter { YamlIter { - yaml: self.into_vec().unwrap_or_else(Vec::new).into_iter(), + yaml: self.into_vec().unwrap_or_default().into_iter(), } } } @@ -366,9 +375,11 @@ impl Iterator for YamlIter { } #[cfg(test)] +#[allow(clippy::bool_assert_comparison)] +#[allow(clippy::float_cmp)] mod test { + use crate::yaml::{vec, Yaml, YamlLoader}; use std::f64; - use crate::yaml::*; #[test] fn test_coerce() { let s = "--- @@ -376,7 +387,7 @@ a: 1 b: 2.2 c: [1, 2] "; - let out = YamlLoader::load_from_str(&s).unwrap(); + let out = YamlLoader::load_from_str(s).unwrap(); let doc = &out[0]; assert_eq!(doc["a"].as_i64().unwrap(), 1i64); assert_eq!(doc["b"].as_f64().unwrap(), 2.2f64); @@ -386,7 +397,7 @@ c: [1, 2] #[test] fn test_empty_doc() { - let s: String = "".to_owned(); + let s: String = String::new(); YamlLoader::load_from_str(&s).unwrap(); let s: String = "---".to_owned(); assert_eq!(YamlLoader::load_from_str(&s).unwrap()[0], Yaml::Null); @@ -425,7 +436,7 @@ a7: 你好 --- 'a scalar' "; - let out = YamlLoader::load_from_str(&s).unwrap(); + let out = YamlLoader::load_from_str(s).unwrap(); assert_eq!(out.len(), 3); } @@ -437,7 +448,7 @@ a1: &DEFAULT b2: d a2: *DEFAULT "; - let out = YamlLoader::load_from_str(&s).unwrap(); + let out = YamlLoader::load_from_str(s).unwrap(); let doc = &out[0]; assert_eq!(doc["a2"]["b1"].as_i64().unwrap(), 4); } @@ -449,7 +460,7 @@ a1: &DEFAULT b1: 4 b2: *DEFAULT "; - let out = YamlLoader::load_from_str(&s).unwrap(); + let out = YamlLoader::load_from_str(s).unwrap(); let doc = &out[0]; assert_eq!(doc["a1"]["b2"], Yaml::BadValue); } @@ -458,7 +469,7 @@ a1: &DEFAULT fn test_github_27() { // https://github.com/chyh1990/yaml-rust/issues/27 let s = "&a"; - let out = YamlLoader::load_from_str(&s).unwrap(); + let out = YamlLoader::load_from_str(s).unwrap(); let doc = &out[0]; assert_eq!(doc.as_str().unwrap(), ""); } @@ -494,7 +505,7 @@ a1: &DEFAULT - +12345 - [ true, false ] "; - let out = YamlLoader::load_from_str(&s).unwrap(); + let out = YamlLoader::load_from_str(s).unwrap(); let doc = &out[0]; assert_eq!(doc[0].as_str().unwrap(), "string"); @@ -531,14 +542,14 @@ a1: &DEFAULT fn test_bad_hyphen() { // See: https://github.com/chyh1990/yaml-rust/issues/23 let s = "{-"; - assert!(YamlLoader::load_from_str(&s).is_err()); + assert!(YamlLoader::load_from_str(s).is_err()); } #[test] fn test_issue_65() { // See: https://github.com/chyh1990/yaml-rust/issues/65 let b = "\n\"ll\\\"ll\\\r\n\"ll\\\"ll\\\r\r\r\rU\r\r\rU"; - assert!(YamlLoader::load_from_str(&b).is_err()); + assert!(YamlLoader::load_from_str(b).is_err()); } #[test] @@ -582,7 +593,7 @@ a1: &DEFAULT - .NAN - !!float .INF "; - let mut out = YamlLoader::load_from_str(&s).unwrap().into_iter(); + let mut out = YamlLoader::load_from_str(s).unwrap().into_iter(); let mut doc = out.next().unwrap().into_iter(); assert_eq!(doc.next().unwrap().into_string().unwrap(), "string"); @@ -614,7 +625,7 @@ b: ~ a: ~ c: ~ "; - let out = YamlLoader::load_from_str(&s).unwrap(); + let out = YamlLoader::load_from_str(s).unwrap(); let first = out.into_iter().next().unwrap(); let mut iter = first.into_hash().unwrap().into_iter(); assert_eq!( @@ -640,7 +651,7 @@ c: ~ 1: important: false "; - let out = YamlLoader::load_from_str(&s).unwrap(); + let out = YamlLoader::load_from_str(s).unwrap(); let first = out.into_iter().next().unwrap(); assert_eq!(first[0]["important"].as_bool().unwrap(), true); } @@ -716,10 +727,10 @@ subcommands3: about: server related commands "#; - let out = YamlLoader::load_from_str(&s).unwrap(); + let out = YamlLoader::load_from_str(s).unwrap(); let doc = &out.into_iter().next().unwrap(); - println!("{:#?}", doc); + println!("{doc:#?}"); assert_eq!(doc["subcommands"][0]["server"], Yaml::Null); assert!(doc["subcommands2"][0]["server"].as_hash().is_some()); assert!(doc["subcommands3"][0]["server"].as_hash().is_some()); diff --git a/saphyr/tests/spec_test.rs b/saphyr/tests/spec_test.rs index 442728f..5e6dfa3 100644 --- a/saphyr/tests/spec_test.rs +++ b/saphyr/tests/spec_test.rs @@ -6,7 +6,7 @@ use yaml_rust::parser::{Event, EventReceiver, Parser}; use yaml_rust::scanner::TScalarStyle; // These names match the names used in the C++ test suite. -#[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))] +#[cfg_attr(feature = "cargo-clippy", allow(clippy::enum_variant_names))] #[derive(Clone, PartialEq, PartialOrd, Debug)] enum TestEvent { OnDocumentStart, @@ -76,24 +76,18 @@ include!("spec_test.rs.inc"); #[test] fn test_mapvec_legal() { - use yaml_rust::yaml::{Array, Hash, Yaml}; + use yaml_rust::yaml::{Hash, Yaml}; use yaml_rust::{YamlEmitter, YamlLoader}; // Emitting a `map>, _>` should result in legal yaml that // we can parse. - let mut key = Array::new(); - key.push(Yaml::Integer(1)); - key.push(Yaml::Integer(2)); - key.push(Yaml::Integer(3)); + let key = vec![Yaml::Integer(1), Yaml::Integer(2), Yaml::Integer(3)]; let mut keyhash = Hash::new(); keyhash.insert(Yaml::String("key".into()), Yaml::Array(key)); - let mut val = Array::new(); - val.push(Yaml::Integer(4)); - val.push(Yaml::Integer(5)); - val.push(Yaml::Integer(6)); + let val = vec![Yaml::Integer(4), Yaml::Integer(5), Yaml::Integer(6)]; let mut hash = Hash::new(); hash.insert(Yaml::Hash(keyhash), Yaml::Array(val)); diff --git a/saphyr/tests/test_round_trip.rs b/saphyr/tests/test_round_trip.rs index dc5e85e..4a383a8 100644 --- a/saphyr/tests/test_round_trip.rs +++ b/saphyr/tests/test_round_trip.rs @@ -7,14 +7,14 @@ fn roundtrip(original: &Yaml) { YamlEmitter::new(&mut emitted).dump(original).unwrap(); let documents = YamlLoader::load_from_str(&emitted).unwrap(); - println!("emitted {}", emitted); + println!("emitted {emitted}"); assert_eq!(documents.len(), 1); assert_eq!(documents[0], *original); } fn double_roundtrip(original: &str) { - let parsed = YamlLoader::load_from_str(&original).unwrap(); + let parsed = YamlLoader::load_from_str(original).unwrap(); let mut serialized = String::new(); YamlEmitter::new(&mut serialized).dump(&parsed[0]).unwrap(); @@ -39,27 +39,32 @@ fn test_colon_in_string() { #[test] fn test_numberlike_strings() { let docs = [ - r#"x: "1234""#, r#"x: "01234""#, r#""1234""#, - r#""01234""#, r#"" 01234""#, r#""0x1234""#, + r#"x: "1234""#, + r#"x: "01234""#, + r#""1234""#, + r#""01234""#, + r#"" 01234""#, + r#""0x1234""#, r#"" 0x1234""#, ]; for doc in &docs { - roundtrip(&Yaml::String(doc.to_string())); - double_roundtrip(&doc); + roundtrip(&Yaml::String((*doc).to_string())); + double_roundtrip(doc); } } -/// Example from https://github.com/chyh1990/yaml-rust/issues/133 +/// Example from #[test] fn test_issue133() { - - let doc = YamlLoader::load_from_str("\"0x123\"").unwrap().pop().unwrap(); + let doc = YamlLoader::load_from_str("\"0x123\"") + .unwrap() + .pop() + .unwrap(); assert_eq!(doc, Yaml::String("0x123".to_string())); let mut out_str = String::new(); YamlEmitter::new(&mut out_str).dump(&doc).unwrap(); let doc2 = YamlLoader::load_from_str(&out_str).unwrap().pop().unwrap(); assert_eq!(doc, doc2); // This failed because the type has changed to a number now - }