From ff679e13d959f25567b82218685a61047bc2f1a6 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Fri, 9 Aug 2019 11:01:43 +0200 Subject: [PATCH 1/6] Implement std::error::Error for errors --- src/parser.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/parser.rs b/src/parser.rs index 06104052..28d73fb0 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -4,6 +4,8 @@ use cow_rc_str::CowRcStr; use smallvec::SmallVec; +use std::error::Error; +use std::fmt; use std::ops::BitOr; use std::ops::Range; use tokenizer::{SourceLocation, SourcePosition, Token, Tokenizer}; @@ -53,6 +55,18 @@ pub enum BasicParseErrorKind<'i> { QualifiedRuleInvalid, } +impl<'i> BasicParseErrorKind<'i> { + fn description(&self) -> &'static str { + match self { + BasicParseErrorKind::UnexpectedToken(_) => "Unexpected token", + BasicParseErrorKind::EndOfInput => "End of input", + BasicParseErrorKind::AtRuleInvalid(_) => "Invalid @ rule", + BasicParseErrorKind::AtRuleBodyInvalid => "Invalid @ rule body", + BasicParseErrorKind::QualifiedRuleInvalid => "Invalid qualified rule", + } + } +} + /// The funamental parsing errors that can be triggered by built-in parsing routines. #[derive(Clone, Debug, PartialEq)] pub struct BasicParseError<'i> { @@ -62,6 +76,14 @@ pub struct BasicParseError<'i> { pub location: SourceLocation, } +impl<'i> fmt::Display for BasicParseError<'i> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "{}", self.kind.description()) + } +} + +impl<'i> Error for BasicParseError<'i> {} + impl<'i, T> From> for ParseError<'i, T> { #[inline] fn from(this: BasicParseError<'i>) -> ParseError<'i, T> { @@ -156,6 +178,17 @@ impl<'i, T> ParseError<'i, T> { } } +impl<'i, T> fmt::Display for ParseError<'i, T> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "{}", match &self.kind { + ParseErrorKind::Basic(basic_kind) => basic_kind.description(), + ParseErrorKind::Custom(_) => "Custom error", + }) + } +} + +impl<'i, T> Error for ParseError<'i, T> where T: fmt::Debug {} + /// The owned input for a parser. pub struct ParserInput<'i> { tokenizer: Tokenizer<'i>, From a1f9e6d1c6a790d4663ce644aeee401fa8c1d106 Mon Sep 17 00:00:00 2001 From: Martijn Groeneveldt Date: Sun, 20 Oct 2019 00:21:07 +0200 Subject: [PATCH 2/6] improve the error implementation --- .gitignore | 1 + procedural-masquerade/lib.rs | 56 +++++++++++++++---------------- src/lib.rs | 4 +-- src/macros.rs | 20 +++++------ src/parser.rs | 31 ++++++++++-------- src/rules_and_declarations.rs | 4 +-- src/serializer.rs | 13 ++++++-- src/tests.rs | 19 +++++++---- src/tokenizer.rs | 62 +++++++++++++++++++++++++++++++++++ 9 files changed, 143 insertions(+), 67 deletions(-) diff --git a/.gitignore b/.gitignore index 0b837eae..4c73520b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ target /Cargo.lock /.cargo/config +.idea \ No newline at end of file diff --git a/procedural-masquerade/lib.rs b/procedural-masquerade/lib.rs index 2736ccf5..bc341206 100644 --- a/procedural-masquerade/lib.rs +++ b/procedural-masquerade/lib.rs @@ -244,33 +244,33 @@ macro_rules! define_invoke_proc_macro { #[doc(hidden)] #[macro_export] macro_rules! $macro_name { - ($proc_macro_name: ident ! $paren: tt) => { - #[derive($proc_macro_name)] - #[allow(unused)] - enum ProceduralMasqueradeDummyType { - // The magic happens here. - // - // We use an `enum` with an explicit discriminant - // because that is the only case where a type definition - // can contain a (const) expression. - // - // `(0, "foo").0` evalutes to 0, with the `"foo"` part ignored. - // - // By the time the `#[proc_macro_derive]` function - // implementing `#[derive($proc_macro_name)]` is called, - // `$paren` has already been replaced with the input of this inner macro, - // but `stringify!` has not been expanded yet. - // - // This how arbitrary tokens can be inserted - // in the input to the `#[proc_macro_derive]` function. - // - // Later, `stringify!(...)` is expanded into a string literal - // which is then ignored. - // Using `stringify!` enables passing arbitrary tokens - // rather than only what can be parsed as a const expression. - Input = (0, stringify! $paren ).0 - } - } - } + ($proc_macro_name: ident ! $paren: tt) => { + #[derive($proc_macro_name)] + #[allow(unused)] + enum ProceduralMasqueradeDummyType { + // The magic happens here. + // + // We use an `enum` with an explicit discriminant + // because that is the only case where a type definition + // can contain a (const) expression. + // + // `(0, "foo").0` evalutes to 0, with the `"foo"` part ignored. + // + // By the time the `#[proc_macro_derive]` function + // implementing `#[derive($proc_macro_name)]` is called, + // `$paren` has already been replaced with the input of this inner macro, + // but `stringify!` has not been expanded yet. + // + // This how arbitrary tokens can be inserted + // in the input to the `#[proc_macro_derive]` function. + // + // Later, `stringify!(...)` is expanded into a string literal + // which is then ignored. + // Using `stringify!` enables passing arbitrary tokens + // rather than only what can be parsed as a const expression. + Input = (0, stringify! $paren ).0 + } + } + } }; } diff --git a/src/lib.rs b/src/lib.rs index 921bc200..de314290 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,10 +81,10 @@ extern crate difference; extern crate encoding_rs; #[doc(hidden)] pub extern crate phf as _internal__phf; -#[cfg(test)] -extern crate serde_json; #[cfg(feature = "serde")] extern crate serde; +#[cfg(test)] +extern crate serde_json; #[cfg(feature = "heapsize")] #[macro_use] extern crate heapsize; diff --git a/src/macros.rs b/src/macros.rs index f40e95e1..8ad9de36 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -125,12 +125,10 @@ macro_rules! cssparser_internal__to_lowercase { #[macro_export] #[doc(hidden)] macro_rules! cssparser_internal__uninit { - ($buffer: ident, $BUFFER_SIZE: expr) => { - { - $buffer = ::std::mem::MaybeUninit::<[u8; $BUFFER_SIZE]>::uninit(); - &mut *($buffer.as_mut_ptr()) - } - } + ($buffer: ident, $BUFFER_SIZE: expr) => {{ + $buffer = ::std::mem::MaybeUninit::<[u8; $BUFFER_SIZE]>::uninit(); + &mut *($buffer.as_mut_ptr()) + }}; } // FIXME: remove this when we require Rust 1.36 @@ -138,12 +136,10 @@ macro_rules! cssparser_internal__uninit { #[macro_export] #[doc(hidden)] macro_rules! cssparser_internal__uninit { - ($buffer: ident, $BUFFER_SIZE: expr) => { - { - $buffer = ::std::mem::uninitialized::<[u8; $BUFFER_SIZE]>(); - &mut $buffer - } - } + ($buffer: ident, $BUFFER_SIZE: expr) => {{ + $buffer = ::std::mem::uninitialized::<[u8; $BUFFER_SIZE]>(); + &mut $buffer + }}; } /// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros. diff --git a/src/parser.rs b/src/parser.rs index 28d73fb0..6dd32799 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -56,13 +56,15 @@ pub enum BasicParseErrorKind<'i> { } impl<'i> BasicParseErrorKind<'i> { - fn description(&self) -> &'static str { + fn description(&self) -> String { match self { - BasicParseErrorKind::UnexpectedToken(_) => "Unexpected token", - BasicParseErrorKind::EndOfInput => "End of input", - BasicParseErrorKind::AtRuleInvalid(_) => "Invalid @ rule", - BasicParseErrorKind::AtRuleBodyInvalid => "Invalid @ rule body", - BasicParseErrorKind::QualifiedRuleInvalid => "Invalid qualified rule", + BasicParseErrorKind::UnexpectedToken(token) => { + format!("Unexpected token: '{}'", token.description()) + } + BasicParseErrorKind::EndOfInput => "End of input".to_owned(), + BasicParseErrorKind::AtRuleInvalid(message) => format!("Invalid @ rule: {}", message), + BasicParseErrorKind::AtRuleBodyInvalid => "Invalid @ rule body".to_owned(), + BasicParseErrorKind::QualifiedRuleInvalid => "Invalid qualified rule".to_owned(), } } } @@ -78,7 +80,7 @@ pub struct BasicParseError<'i> { impl<'i> fmt::Display for BasicParseError<'i> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "{}", self.kind.description()) + formatter.write_str(self.kind.description().as_str()) } } @@ -178,16 +180,19 @@ impl<'i, T> ParseError<'i, T> { } } -impl<'i, T> fmt::Display for ParseError<'i, T> { +impl<'i, T> fmt::Display for ParseError<'i, T> +where + T: fmt::Display, +{ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "{}", match &self.kind { - ParseErrorKind::Basic(basic_kind) => basic_kind.description(), - ParseErrorKind::Custom(_) => "Custom error", - }) + match &self.kind { + ParseErrorKind::Basic(basic_kind) => formatter.write_str(&basic_kind.description()), + ParseErrorKind::Custom(custom_type) => custom_type.fmt(formatter), + } } } -impl<'i, T> Error for ParseError<'i, T> where T: fmt::Debug {} +impl<'i, T> Error for ParseError<'i, T> where T: Error {} /// The owned input for a parser. pub struct ParserInput<'i> { diff --git a/src/rules_and_declarations.rs b/src/rules_and_declarations.rs index 1d040efb..4ca6960d 100644 --- a/src/rules_and_declarations.rs +++ b/src/rules_and_declarations.rs @@ -268,9 +268,7 @@ where let start = self.input.state(); // FIXME: remove intermediate variable when lifetimes are non-lexical let ident = match self.input.next_including_whitespace_and_comments() { - Ok(&Token::WhiteSpace(_)) | Ok(&Token::Comment(_)) | Ok(&Token::Semicolon) => { - continue - } + Ok(&Token::WhiteSpace(_)) | Ok(&Token::Comment(_)) | Ok(&Token::Semicolon) => continue, Ok(&Token::Ident(ref name)) => Ok(Ok(name.clone())), Ok(&Token::AtKeyword(ref name)) => Ok(Err(name.clone())), Ok(token) => Err(token.clone()), diff --git a/src/serializer.rs b/src/serializer.rs index fb0462cc..2ff03f3a 100644 --- a/src/serializer.rs +++ b/src/serializer.rs @@ -451,7 +451,14 @@ impl TokenSerializationType { ), Number => matches!( other.0, - Ident | Function | UrlOrBadUrl | DelimMinus | Number | Percentage | DelimPercent | Dimension + Ident + | Function + | UrlOrBadUrl + | DelimMinus + | Number + | Percentage + | DelimPercent + | Dimension ), DelimAt => matches!(other.0, Ident | Function | UrlOrBadUrl | DelimMinus), DelimDotOrPlus => matches!(other.0, Number | Percentage | Dimension), @@ -459,7 +466,9 @@ impl TokenSerializationType { DelimBar => matches!(other.0, DelimEquals | DelimBar | DashMatch), DelimSlash => matches!(other.0, DelimAsterisk | SubstringMatch), Nothing | WhiteSpace | Percentage | UrlOrBadUrl | Function | CDC | OpenParen - | DashMatch | SubstringMatch | DelimQuestion | DelimEquals | DelimPercent | Other => false, + | DashMatch | SubstringMatch | DelimQuestion | DelimEquals | DelimPercent | Other => { + false + } } } } diff --git a/src/tests.rs b/src/tests.rs index a1f08bcb..7b805fb9 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -6,7 +6,7 @@ extern crate test; use encoding_rs; -use serde_json::{self, Value, json, Map}; +use serde_json::{self, json, Map, Value}; #[cfg(feature = "bench")] use self::test::Bencher; @@ -30,7 +30,7 @@ fn almost_equals(a: &Value, b: &Value) -> bool { let a = a.as_f64().unwrap(); let b = b.as_f64().unwrap(); (a - b).abs() <= a.abs() * 1e-6 - }, + } (&Value::Bool(a), &Value::Bool(b)) => a == b, (&Value::String(ref a), &Value::String(ref b)) => a == b, @@ -410,15 +410,16 @@ fn unicode_range() { Ok(None) } }); - result.unwrap() + result + .unwrap() .iter() - .map(|v| - if let Some((v0, v1)) = v{ + .map(|v| { + if let Some((v0, v1)) = v { json!([v0, v1]) } else { Value::Null } - ) + }) .collect::>() .to_json() }); @@ -809,7 +810,11 @@ trait ToJson { fn to_json(&self) -> Value; } -impl ToJson for T where T: Clone, Value: From { +impl ToJson for T +where + T: Clone, + Value: From, +{ fn to_json(&self) -> Value { Value::from(self.clone()) } diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 73cb031a..642ba63c 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -191,6 +191,68 @@ impl<'a> Token<'a> { BadUrl(_) | BadString(_) | CloseParenthesis | CloseSquareBracket | CloseCurlyBracket ) } + + pub(crate) fn description(&self) -> String { + match self { + Ident(name) => format!("A ident token '{}'", name), + AtKeyword(value) => format!("The value '{}' does not include the `@` marker", value), + Hash(value) => format!("The value '{}' does not include the `#` marker", value), + IDHash(value) => format!( + "The value '{}' does not include the `#` marker, but has a valid ID selector", + value + ), + QuotedString(value) => format!("The value '{}' does not include the quotes", value), + UnquotedUrl(value) => format!( + "The value '{}' does not include the `url(` `)` markers.", + value + ), + Delim(character) => format!("'{}'", character), + Number { + has_sign, value, .. + } => { + let sign = if has_sign.clone() { '-' } else { '+' }; + format!("{}{}", sign, value.to_string()) + } + Percentage { + has_sign, + unit_value, + .. + } => { + let sign = if has_sign.clone() { '-' } else { '+' }; + format!("{}{}%", sign, unit_value.to_string()) + } + Dimension { + has_sign, + value, + unit, + .. + } => { + let sign = if has_sign.clone() { '-' } else { '+' }; + format!("{}{} {}", sign, value.to_string(), unit) + } + WhiteSpace(whitespace) => format!("whitespace: '{}'", whitespace), + Comment(comment) => format!("The comment: '{}'", comment), + Colon => String::from(":"), + Semicolon => String::from(";"), + Comma => String::from(","), + IncludeMatch => String::from("~="), + DashMatch => String::from("|="), + PrefixMatch => String::from("^="), + SuffixMatch => String::from("$="), + SubstringMatch => String::from("*="), + CDO => String::from(""), + Function(name) => format!("The value ({}) does not include the `(` marker", name), + ParenthesisBlock => String::from("("), + SquareBracketBlock => String::from("["), + CurlyBracketBlock => String::from("{"), + BadUrl(url) => format!("Bad url: '{}'", url), + BadString(string) => format!("Bad string: '{}'", string), + CloseParenthesis => "Unclosed parenthesis".to_owned(), + CloseSquareBracket => "Unclosed square bracket".to_owned(), + CloseCurlyBracket => "Unclosed curly bracket".to_owned(), + } + } } #[derive(Clone)] From 51312ea14ff89f55f6632642409f6bc4623b0026 Mon Sep 17 00:00:00 2001 From: Martijn Groeneveldt Date: Mon, 21 Oct 2019 20:48:11 +0200 Subject: [PATCH 3/6] Add best effort error descriptions --- src/parser.rs | 15 +++++++++++++-- src/rules_and_declarations.rs | 4 +++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 6dd32799..9f4dfe93 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -84,7 +84,11 @@ impl<'i> fmt::Display for BasicParseError<'i> { } } -impl<'i> Error for BasicParseError<'i> {} +impl<'i> Error for BasicParseError<'i> { + fn description(&self) -> &str { + "A BasicParseError has occurred, please use the Display trait to determine it's kind" + } +} impl<'i, T> From> for ParseError<'i, T> { #[inline] @@ -192,7 +196,14 @@ where } } -impl<'i, T> Error for ParseError<'i, T> where T: Error {} +impl<'i, T> Error for ParseError<'i, T> +where + T: Error, +{ + fn description(&self) -> &str { + "A ParseError has occurred, please use the Display trait to determine it's kind" + } +} /// The owned input for a parser. pub struct ParserInput<'i> { diff --git a/src/rules_and_declarations.rs b/src/rules_and_declarations.rs index 4ca6960d..1d040efb 100644 --- a/src/rules_and_declarations.rs +++ b/src/rules_and_declarations.rs @@ -268,7 +268,9 @@ where let start = self.input.state(); // FIXME: remove intermediate variable when lifetimes are non-lexical let ident = match self.input.next_including_whitespace_and_comments() { - Ok(&Token::WhiteSpace(_)) | Ok(&Token::Comment(_)) | Ok(&Token::Semicolon) => continue, + Ok(&Token::WhiteSpace(_)) | Ok(&Token::Comment(_)) | Ok(&Token::Semicolon) => { + continue + } Ok(&Token::Ident(ref name)) => Ok(Ok(name.clone())), Ok(&Token::AtKeyword(ref name)) => Ok(Err(name.clone())), Ok(token) => Err(token.clone()), From 47d1915648a32f55f1fd2950d19752fe77c8311b Mon Sep 17 00:00:00 2001 From: Martijn Groeneveldt Date: Mon, 21 Oct 2019 21:02:53 +0200 Subject: [PATCH 4/6] Fix a EOL and cargo fmt --- .gitignore | 2 +- build/match_byte.rs | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4c73520b..39d7405d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ target /Cargo.lock /.cargo/config -.idea \ No newline at end of file +.idea diff --git a/build/match_byte.rs b/build/match_byte.rs index 09308590..0ec4cdde 100644 --- a/build/match_byte.rs +++ b/build/match_byte.rs @@ -73,7 +73,12 @@ fn get_byte_from_expr_lit(expr: &Box) -> u8 { } /// Parse a pattern and fill the table accordingly -fn parse_pat_to_table<'a>(pat: &'a syn::Pat, case_id: u8, wildcard: &mut Option<&'a syn::Ident>, table: &mut [u8; 256]) { +fn parse_pat_to_table<'a>( + pat: &'a syn::Pat, + case_id: u8, + wildcard: &mut Option<&'a syn::Ident>, + table: &mut [u8; 256], +) { match pat { &syn::Pat::Lit(syn::PatLit { ref expr, .. }) => { let value = get_byte_from_expr_lit(expr); @@ -108,7 +113,7 @@ fn parse_pat_to_table<'a>(pat: &'a syn::Pat, case_id: u8, wildcard: &mut Option< *byte = case_id; } } - }, + } &syn::Pat::Or(syn::PatOr { ref cases, .. }) => { for case in cases { parse_pat_to_table(case, case_id, wildcard, table); From 9b2246cb9a35dd8f15a5fee4f578005606a5b19f Mon Sep 17 00:00:00 2001 From: dutchmartin Date: Mon, 27 Apr 2020 17:19:52 +0200 Subject: [PATCH 5/6] Process CR and simplyly the PR --- procedural-masquerade/lib.rs | 56 ++++++++++++++++---------------- src/parser.rs | 2 +- src/tokenizer.rs | 62 ------------------------------------ 3 files changed, 29 insertions(+), 91 deletions(-) diff --git a/procedural-masquerade/lib.rs b/procedural-masquerade/lib.rs index bc341206..2736ccf5 100644 --- a/procedural-masquerade/lib.rs +++ b/procedural-masquerade/lib.rs @@ -244,33 +244,33 @@ macro_rules! define_invoke_proc_macro { #[doc(hidden)] #[macro_export] macro_rules! $macro_name { - ($proc_macro_name: ident ! $paren: tt) => { - #[derive($proc_macro_name)] - #[allow(unused)] - enum ProceduralMasqueradeDummyType { - // The magic happens here. - // - // We use an `enum` with an explicit discriminant - // because that is the only case where a type definition - // can contain a (const) expression. - // - // `(0, "foo").0` evalutes to 0, with the `"foo"` part ignored. - // - // By the time the `#[proc_macro_derive]` function - // implementing `#[derive($proc_macro_name)]` is called, - // `$paren` has already been replaced with the input of this inner macro, - // but `stringify!` has not been expanded yet. - // - // This how arbitrary tokens can be inserted - // in the input to the `#[proc_macro_derive]` function. - // - // Later, `stringify!(...)` is expanded into a string literal - // which is then ignored. - // Using `stringify!` enables passing arbitrary tokens - // rather than only what can be parsed as a const expression. - Input = (0, stringify! $paren ).0 - } - } - } + ($proc_macro_name: ident ! $paren: tt) => { + #[derive($proc_macro_name)] + #[allow(unused)] + enum ProceduralMasqueradeDummyType { + // The magic happens here. + // + // We use an `enum` with an explicit discriminant + // because that is the only case where a type definition + // can contain a (const) expression. + // + // `(0, "foo").0` evalutes to 0, with the `"foo"` part ignored. + // + // By the time the `#[proc_macro_derive]` function + // implementing `#[derive($proc_macro_name)]` is called, + // `$paren` has already been replaced with the input of this inner macro, + // but `stringify!` has not been expanded yet. + // + // This how arbitrary tokens can be inserted + // in the input to the `#[proc_macro_derive]` function. + // + // Later, `stringify!(...)` is expanded into a string literal + // which is then ignored. + // Using `stringify!` enables passing arbitrary tokens + // rather than only what can be parsed as a const expression. + Input = (0, stringify! $paren ).0 + } + } + } }; } diff --git a/src/parser.rs b/src/parser.rs index 098c023b..8142e8dd 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -59,7 +59,7 @@ impl<'i> BasicParseErrorKind<'i> { fn description(&self) -> String { match self { BasicParseErrorKind::UnexpectedToken(token) => { - format!("Unexpected token: '{}'", token.description()) + format!("Unexpected token: {:?}", token) } BasicParseErrorKind::EndOfInput => "End of input".to_owned(), BasicParseErrorKind::AtRuleInvalid(message) => format!("Invalid @ rule: {}", message), diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 0794c7f5..62f38683 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -191,68 +191,6 @@ impl<'a> Token<'a> { BadUrl(_) | BadString(_) | CloseParenthesis | CloseSquareBracket | CloseCurlyBracket ) } - - pub(crate) fn description(&self) -> String { - match self { - Ident(name) => format!("A ident token '{}'", name), - AtKeyword(value) => format!("The value '{}' does not include the `@` marker", value), - Hash(value) => format!("The value '{}' does not include the `#` marker", value), - IDHash(value) => format!( - "The value '{}' does not include the `#` marker, but has a valid ID selector", - value - ), - QuotedString(value) => format!("The value '{}' does not include the quotes", value), - UnquotedUrl(value) => format!( - "The value '{}' does not include the `url(` `)` markers.", - value - ), - Delim(character) => format!("'{}'", character), - Number { - has_sign, value, .. - } => { - let sign = if has_sign.clone() { '-' } else { '+' }; - format!("{}{}", sign, value.to_string()) - } - Percentage { - has_sign, - unit_value, - .. - } => { - let sign = if has_sign.clone() { '-' } else { '+' }; - format!("{}{}%", sign, unit_value.to_string()) - } - Dimension { - has_sign, - value, - unit, - .. - } => { - let sign = if has_sign.clone() { '-' } else { '+' }; - format!("{}{} {}", sign, value.to_string(), unit) - } - WhiteSpace(whitespace) => format!("whitespace: '{}'", whitespace), - Comment(comment) => format!("The comment: '{}'", comment), - Colon => String::from(":"), - Semicolon => String::from(";"), - Comma => String::from(","), - IncludeMatch => String::from("~="), - DashMatch => String::from("|="), - PrefixMatch => String::from("^="), - SuffixMatch => String::from("$="), - SubstringMatch => String::from("*="), - CDO => String::from(""), - Function(name) => format!("The value ({}) does not include the `(` marker", name), - ParenthesisBlock => String::from("("), - SquareBracketBlock => String::from("["), - CurlyBracketBlock => String::from("{"), - BadUrl(url) => format!("Bad url: '{}'", url), - BadString(string) => format!("Bad string: '{}'", string), - CloseParenthesis => "Unclosed parenthesis".to_owned(), - CloseSquareBracket => "Unclosed square bracket".to_owned(), - CloseCurlyBracket => "Unclosed curly bracket".to_owned(), - } - } } #[derive(Clone)] From c962d4a32b9dc3efd71bc4e1a41dbcbe5c606a76 Mon Sep 17 00:00:00 2001 From: Abraham Toriz Date: Wed, 2 Feb 2022 08:38:35 -0600 Subject: [PATCH 6/6] impl fmt::Display for BasicParseErrorKind --- src/parser.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 8efaa129..9624056e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -55,16 +55,16 @@ pub enum BasicParseErrorKind<'i> { QualifiedRuleInvalid, } -impl<'i> BasicParseErrorKind<'i> { - fn description(&self) -> String { +impl<'i> fmt::Display for BasicParseErrorKind<'i> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self { BasicParseErrorKind::UnexpectedToken(token) => { - format!("Unexpected token: {:?}", token) + write!(formatter, "Unexpected token: {:?}", token) } - BasicParseErrorKind::EndOfInput => "End of input".to_owned(), - BasicParseErrorKind::AtRuleInvalid(message) => format!("Invalid @ rule: {}", message), - BasicParseErrorKind::AtRuleBodyInvalid => "Invalid @ rule body".to_owned(), - BasicParseErrorKind::QualifiedRuleInvalid => "Invalid qualified rule".to_owned(), + BasicParseErrorKind::EndOfInput => formatter.write_str("End of input"), + BasicParseErrorKind::AtRuleInvalid(message) => write!(formatter, "Invalid @ rule: {}", message), + BasicParseErrorKind::AtRuleBodyInvalid => formatter.write_str("Invalid @ rule body"), + BasicParseErrorKind::QualifiedRuleInvalid => formatter.write_str("Invalid qualified rule"), } } } @@ -79,7 +79,7 @@ pub struct BasicParseError<'i> { impl<'i> fmt::Display for BasicParseError<'i> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str(self.kind.description().as_str()) + self.kind.fmt(formatter) } } @@ -189,7 +189,7 @@ where { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.kind { - ParseErrorKind::Basic(basic_kind) => formatter.write_str(&basic_kind.description()), + ParseErrorKind::Basic(basic_kind) => basic_kind.fmt(formatter), ParseErrorKind::Custom(custom_type) => custom_type.fmt(formatter), } }