From 47c25ec039033ad06efe1afcf2f7590f850a2a7d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 22 Oct 2019 15:20:20 +0200 Subject: [PATCH 1/4] rustfmt --- build/match_byte.rs | 9 +++++++-- src/rules_and_declarations.rs | 4 +--- src/serializer.rs | 13 +++++++++++-- src/tests.rs | 19 ++++++++++++------- 4 files changed, 31 insertions(+), 14 deletions(-) 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); diff --git a/src/rules_and_declarations.rs b/src/rules_and_declarations.rs index 1f93af2c..424310b7 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()) } From e31b38d16f9786ea7bca134c667db63f96687398 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 22 Oct 2019 15:54:55 +0200 Subject: [PATCH 2/4] Use the 2018 edition --- Cargo.toml | 1 + build.rs | 9 +---- build/match_byte.rs | 3 +- src/lib.rs | 65 ++++++++++------------------------- src/macros.rs | 7 ++-- src/nth.rs | 1 + src/parser.rs | 10 +++--- src/rules_and_declarations.rs | 18 +++++----- src/serializer.rs | 3 +- src/size_of_tests.rs | 18 +++++----- src/tests.rs | 10 +++--- src/tokenizer.rs | 8 ++--- src/unicode_range.rs | 4 +-- 13 files changed, 64 insertions(+), 93 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e38aa6f2..27e6eceb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ readme = "README.md" keywords = ["css", "syntax", "parser"] license = "MPL-2.0" build = "build.rs" +edition = "2018" exclude = ["src/css-parsing-tests/**", "src/big-data-url.css"] diff --git a/build.rs b/build.rs index 7a73ab18..07a72ffe 100644 --- a/build.rs +++ b/build.rs @@ -2,12 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#[macro_use] -extern crate quote; -#[macro_use] -extern crate syn; -extern crate proc_macro2; - #[cfg(feature = "dummy_match_byte")] mod codegen { pub fn main() {} @@ -19,7 +13,6 @@ mod match_byte; #[cfg(not(feature = "dummy_match_byte"))] mod codegen { - use match_byte; use std::env; use std::path::Path; use std::thread::Builder; @@ -35,7 +28,7 @@ mod codegen { let handle = Builder::new() .stack_size(128 * 1024 * 1024) .spawn(move || { - match_byte::expand(&input, &output); + crate::match_byte::expand(&input, &output); }) .unwrap(); diff --git a/build/match_byte.rs b/build/match_byte.rs index 0ec4cdde..edc057e6 100644 --- a/build/match_byte.rs +++ b/build/match_byte.rs @@ -2,13 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use quote::ToTokens; +use quote::{quote, ToTokens}; use std::fs::File; use std::io::{Read, Write}; use std::path::Path; use syn; use syn::fold::Fold; use syn::parse::{Parse, ParseStream, Result}; +use syn::{parse_quote, Token}; use proc_macro2::{Span, TokenStream}; diff --git a/src/lib.rs b/src/lib.rs index f6bab801..1168121b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,56 +67,27 @@ fn parse_border_spacing(_context: &ParserContext, input: &mut Parser) #![recursion_limit = "200"] // For color::parse_color_keyword -extern crate dtoa_short; -extern crate itoa; -#[macro_use] -extern crate cssparser_macros; -#[macro_use] -extern crate matches; -#[cfg(test)] -extern crate difference; -#[cfg(test)] -extern crate encoding_rs; -#[doc(hidden)] -pub extern crate phf as _internal__phf; -#[cfg(feature = "serde")] -extern crate serde; -#[cfg(test)] -extern crate serde_json; -#[cfg(feature = "heapsize")] -#[macro_use] -extern crate heapsize; -extern crate smallvec; - -pub use cssparser_macros::*; - -pub use color::{ +pub use crate::color::{ parse_color_keyword, AngleOrNumber, Color, ColorComponentParser, NumberOrPercentage, RGBA, }; -pub use cow_rc_str::CowRcStr; -pub use from_bytes::{stylesheet_encoding, EncodingSupport}; -pub use nth::parse_nth; -pub use parser::{BasicParseError, BasicParseErrorKind, ParseError, ParseErrorKind}; -pub use parser::{Delimiter, Delimiters, Parser, ParserInput, ParserState}; -pub use rules_and_declarations::parse_important; -pub use rules_and_declarations::{parse_one_declaration, DeclarationListParser, DeclarationParser}; -pub use rules_and_declarations::{parse_one_rule, RuleListParser}; -pub use rules_and_declarations::{AtRuleParser, AtRuleType, QualifiedRuleParser}; -pub use serializer::{ - serialize_identifier, serialize_name, serialize_string, CssStringWriter, ToCss, - TokenSerializationType, -}; -pub use tokenizer::{SourceLocation, SourcePosition, Token}; -pub use unicode_range::UnicodeRange; - -// For macros +pub use crate::cow_rc_str::CowRcStr; +pub use crate::from_bytes::{stylesheet_encoding, EncodingSupport}; #[doc(hidden)] -pub use macros::_internal__to_lowercase; - -// For macros when used in this crate. Unsure how $crate works with procedural-masquerade. -mod cssparser { - pub use _internal__phf; -} +pub use crate::macros::_internal__to_lowercase; +pub use crate::nth::parse_nth; +pub use crate::parser::{BasicParseError, BasicParseErrorKind, ParseError, ParseErrorKind}; +pub use crate::parser::{Delimiter, Delimiters, Parser, ParserInput, ParserState}; +pub use crate::rules_and_declarations::{parse_important, parse_one_declaration}; +pub use crate::rules_and_declarations::{parse_one_rule, RuleListParser}; +pub use crate::rules_and_declarations::{AtRuleParser, AtRuleType, QualifiedRuleParser}; +pub use crate::rules_and_declarations::{DeclarationListParser, DeclarationParser}; +pub use crate::serializer::{serialize_identifier, serialize_name, serialize_string}; +pub use crate::serializer::{CssStringWriter, ToCss, TokenSerializationType}; +pub use crate::tokenizer::{SourceLocation, SourcePosition, Token}; +pub use crate::unicode_range::UnicodeRange; +pub use cssparser_macros::*; +#[doc(hidden)] +pub use phf as _internal__phf; #[macro_use] mod macros; diff --git a/src/macros.rs b/src/macros.rs index ccac001d..e74019da 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use matches::matches; use std::mem::MaybeUninit; /// Expands to a `match` expression with string patterns, @@ -40,7 +41,7 @@ macro_rules! match_ignore_ascii_case { // rather than expression/statement context, // even though the macro only expands to items. mod cssparser_internal { - cssparser_internal__assert_ascii_lowercase__max_len! { + $crate::cssparser_internal__assert_ascii_lowercase__max_len! { match x { $( $match_body )* } } } @@ -90,8 +91,8 @@ macro_rules! ascii_case_insensitive_phf_map { mod cssparser_internal { use $crate::_internal__phf::{Map, phf_map}; #[allow(unused)] use super::*; - cssparser_internal__max_len!( $( $key )+ ); - cssparser_internal__phf_map!( $ValueType $( $key $value )+ ); + $crate::cssparser_internal__max_len!( $( $key )+ ); + $crate::cssparser_internal__phf_map!( $ValueType $( $key $value )+ ); } cssparser_internal__to_lowercase!(input, cssparser_internal::MAX_LENGTH => lowercase); lowercase.and_then(|s| cssparser_internal::MAP.get(s)) diff --git a/src/nth.rs b/src/nth.rs index 939a42c0..d436edaa 100644 --- a/src/nth.rs +++ b/src/nth.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::{BasicParseError, Parser, ParserInput, Token}; +use matches::matches; /// Parse the *An+B* notation, as found in the `:nth-child()` selector. /// The input is typically the arguments of a function, diff --git a/src/parser.rs b/src/parser.rs index 06104052..02f3737e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2,11 +2,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use cow_rc_str::CowRcStr; +use crate::cow_rc_str::CowRcStr; +use crate::tokenizer::{SourceLocation, SourcePosition, Token, Tokenizer}; use smallvec::SmallVec; use std::ops::BitOr; use std::ops::Range; -use tokenizer::{SourceLocation, SourcePosition, Token, Tokenizer}; /// A capture of the internal state of a `Parser` (including the position within the input), /// obtained from the `Parser::position` method. @@ -125,7 +125,7 @@ impl<'i, T> ParseErrorKind<'i, T> { /// Extensible parse errors that can be encountered by client parsing implementations. #[derive(Clone, Debug, PartialEq)] -pub struct ParseError<'i, E: 'i> { +pub struct ParseError<'i, E> { /// Details of this error pub kind: ParseErrorKind<'i, E>, /// Location where this error occurred @@ -195,7 +195,7 @@ impl<'i> ParserInput<'i> { /// A CSS parser that borrows its `&str` input, /// yields `Token`s, /// and keeps track of nested blocks and functions. -pub struct Parser<'i: 't, 't> { +pub struct Parser<'i, 't> { input: &'t mut ParserInput<'i>, /// If `Some(_)`, .parse_nested_block() can be called. at_start_of: Option, @@ -504,7 +504,7 @@ impl<'i: 't, 't> Parser<'i, 't> { /// The old name of `try_parse`, which requires raw identifiers in the Rust 2018 edition. #[inline] - pub fn try(&mut self, thing: F) -> Result + pub fn r#try(&mut self, thing: F) -> Result where F: FnOnce(&mut Parser<'i, 't>) -> Result, { diff --git a/src/rules_and_declarations.rs b/src/rules_and_declarations.rs index 424310b7..6b4fc8e7 100644 --- a/src/rules_and_declarations.rs +++ b/src/rules_and_declarations.rs @@ -6,8 +6,8 @@ use super::{BasicParseError, BasicParseErrorKind, Delimiter}; use super::{ParseError, Parser, SourceLocation, Token}; -use cow_rc_str::CowRcStr; -use parser::{parse_nested_block, parse_until_after, parse_until_before, ParserState}; +use crate::cow_rc_str::CowRcStr; +use crate::parser::{parse_nested_block, parse_until_after, parse_until_before, ParserState}; /// Parse `!important`. /// @@ -221,7 +221,7 @@ pub trait QualifiedRuleParser<'i> { } /// Provides an iterator for declaration list parsing. -pub struct DeclarationListParser<'i: 't, 't: 'a, 'a, P> { +pub struct DeclarationListParser<'i, 't, 'a, P> { /// The input given to `DeclarationListParser::new` pub input: &'a mut Parser<'i, 't>, @@ -229,7 +229,7 @@ pub struct DeclarationListParser<'i: 't, 't: 'a, 'a, P> { pub parser: P, } -impl<'i: 't, 't: 'a, 'a, I, P, E: 'i> DeclarationListParser<'i, 't, 'a, P> +impl<'i, 't, 'a, I, P, E: 'i> DeclarationListParser<'i, 't, 'a, P> where P: DeclarationParser<'i, Declaration = I, Error = E> + AtRuleParser<'i, AtRule = I, Error = E>, { @@ -257,7 +257,7 @@ where /// `DeclarationListParser` is an iterator that yields `Ok(_)` for a valid declaration or at-rule /// or `Err(())` for an invalid one. -impl<'i: 't, 't: 'a, 'a, I, P, E: 'i> Iterator for DeclarationListParser<'i, 't, 'a, P> +impl<'i, 't, 'a, I, P, E: 'i> Iterator for DeclarationListParser<'i, 't, 'a, P> where P: DeclarationParser<'i, Declaration = I, Error = E> + AtRuleParser<'i, AtRule = I, Error = E>, { @@ -306,7 +306,7 @@ where } /// Provides an iterator for rule list parsing. -pub struct RuleListParser<'i: 't, 't: 'a, 'a, P> { +pub struct RuleListParser<'i, 't, 'a, P> { /// The input given to `RuleListParser::new` pub input: &'a mut Parser<'i, 't>, @@ -317,7 +317,7 @@ pub struct RuleListParser<'i: 't, 't: 'a, 'a, P> { any_rule_so_far: bool, } -impl<'i: 't, 't: 'a, 'a, R, P, E: 'i> RuleListParser<'i, 't, 'a, P> +impl<'i, 't, 'a, R, P, E: 'i> RuleListParser<'i, 't, 'a, P> where P: QualifiedRuleParser<'i, QualifiedRule = R, Error = E> + AtRuleParser<'i, AtRule = R, Error = E>, @@ -358,7 +358,7 @@ where } /// `RuleListParser` is an iterator that yields `Ok(_)` for a rule or `Err(())` for an invalid one. -impl<'i: 't, 't: 'a, 'a, R, P, E: 'i> Iterator for RuleListParser<'i, 't, 'a, P> +impl<'i, 't, 'a, R, P, E: 'i> Iterator for RuleListParser<'i, 't, 'a, P> where P: QualifiedRuleParser<'i, QualifiedRule = R, Error = E> + AtRuleParser<'i, AtRule = R, Error = E>, @@ -467,7 +467,7 @@ where }) } -fn parse_at_rule<'i: 't, 't, P, E>( +fn parse_at_rule<'i, 't, P, E>( start: &ParserState, name: CowRcStr<'i>, input: &mut Parser<'i, 't>, diff --git a/src/serializer.rs b/src/serializer.rs index 2ff03f3a..d7f27044 100644 --- a/src/serializer.rs +++ b/src/serializer.rs @@ -4,6 +4,7 @@ use dtoa_short::{self, Notation}; use itoa; +use matches::matches; use std::fmt::{self, Write}; use std::io; use std::str; @@ -293,7 +294,7 @@ where /// Ok(()) /// } /// ``` -pub struct CssStringWriter<'a, W: 'a> { +pub struct CssStringWriter<'a, W> { inner: &'a mut W, } diff --git a/src/size_of_tests.rs b/src/size_of_tests.rs index 6a1ee328..7e39e4c6 100644 --- a/src/size_of_tests.rs +++ b/src/size_of_tests.rs @@ -2,9 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use cow_rc_str::CowRcStr; +use crate::cow_rc_str::CowRcStr; +use crate::tokenizer::Token; use std::borrow::Cow; -use tokenizer::Token; macro_rules! size_of_test { ($testname: ident, $t: ty, $expected_size: expr) => { @@ -41,19 +41,19 @@ size_of_test!(token, Token, 32); size_of_test!(std_cow_str, Cow<'static, str>, 32); size_of_test!(cow_rc_str, CowRcStr, 16); -size_of_test!(tokenizer, ::tokenizer::Tokenizer, 72); +size_of_test!(tokenizer, crate::tokenizer::Tokenizer, 72); size_of_test!( parser_input, - ::parser::ParserInput, + crate::parser::ParserInput, if cfg!(rustc_has_pr45225) { 136 } else { 144 } ); -size_of_test!(parser, ::parser::Parser, 16); -size_of_test!(source_position, ::SourcePosition, 8); -size_of_test!(parser_state, ::ParserState, 24); +size_of_test!(parser, crate::parser::Parser, 16); +size_of_test!(source_position, crate::SourcePosition, 8); +size_of_test!(parser_state, crate::ParserState, 24); -size_of_test!(basic_parse_error, ::BasicParseError, 48); +size_of_test!(basic_parse_error, crate::BasicParseError, 48); size_of_test!( parse_error_lower_bound, - ::ParseError<()>, + crate::ParseError<()>, if cfg!(rustc_has_pr45225) { 48 } else { 56 } ); diff --git a/src/tests.rs b/src/tests.rs index 7b805fb9..9658521b 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -6,6 +6,7 @@ extern crate test; use encoding_rs; +use matches::matches; use serde_json::{self, json, Map, Value}; #[cfg(feature = "bench")] @@ -468,10 +469,11 @@ fn serializer(preserve_comments: bool) { _ => None, }; if let Some(closing_token) = closing_token { - let result: Result<_, ParseError<()>> = input.parse_nested_block(|input| { - write_to(previous_token, input, string, preserve_comments); - Ok(()) - }); + let result: Result<_, ParseError<()>> = + input.parse_nested_block(|input| { + write_to(previous_token, input, string, preserve_comments); + Ok(()) + }); result.unwrap(); closing_token.to_css(string).unwrap(); } diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 73cb031a..62f38683 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -4,14 +4,14 @@ // https://drafts.csswg.org/css-syntax/#tokenization +use self::Token::*; +use crate::cow_rc_str::CowRcStr; +use crate::parser::ParserState; +use matches::matches; use std::char; use std::i32; use std::ops::Range; -use self::Token::*; -use cow_rc_str::CowRcStr; -use parser::ParserState; - /// One of the pieces the CSS input is broken into. /// /// Some components use `Cow` in order to borrow from the original input string diff --git a/src/unicode_range.rs b/src/unicode_range.rs index f5325a0c..68f7811a 100644 --- a/src/unicode_range.rs +++ b/src/unicode_range.rs @@ -4,10 +4,10 @@ //! https://drafts.csswg.org/css-syntax/#urange +use crate::tokenizer::Token; +use crate::{BasicParseError, Parser, ToCss}; use std::char; use std::fmt; -use tokenizer::Token; -use {BasicParseError, Parser, ToCss}; /// One contiguous range of code points. /// From 4c363542c003ead35ab6efdb2db90fdbfadd09aa Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 22 Oct 2019 15:17:28 +0200 Subject: [PATCH 3/4] Fix using the `match_ignore_ascii_case` macro inside another macro expansion --- Cargo.toml | 4 +- macros/Cargo.toml | 2 +- macros/lib.rs | 111 ++++++++++++++++------------------------------ src/macros.rs | 20 ++++++--- src/tests.rs | 31 ++++++++++++- 5 files changed, 86 insertions(+), 82 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 27e6eceb..daefa561 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cssparser" -version = "0.26.0" +version = "0.27.0" authors = [ "Simon Sapin " ] description = "Rust implementation of CSS Syntax Level 3" @@ -20,7 +20,7 @@ difference = "2.0" encoding_rs = "0.8" [dependencies] -cssparser-macros = {path = "./macros", version = "0.4"} +cssparser-macros = {path = "./macros", version = "0.5"} dtoa-short = "0.3" heapsize = {version = ">= 0.3, < 0.5", optional = true} itoa = "0.4" diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 17b42918..f849db1c 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cssparser-macros" -version = "0.4.0" +version = "0.5.0" authors = ["Simon Sapin "] description = "Procedural macros for cssparser" documentation = "https://docs.rs/cssparser-macros/" diff --git a/macros/lib.rs b/macros/lib.rs index 8d768f48..070e1f5c 100644 --- a/macros/lib.rs +++ b/macros/lib.rs @@ -6,103 +6,72 @@ extern crate proc_macro; use proc_macro::TokenStream; -/// Input: a `match` expression. -/// -/// Output: a `MAX_LENGTH` constant with the length of the longest string pattern. -/// -/// Panic if the arms contain non-string patterns, -/// or string patterns that contains ASCII uppercase letters. +/// Implementation detail of the `match_ignore_ascii_case!` macro #[allow(non_snake_case)] #[proc_macro] -pub fn cssparser_internal__assert_ascii_lowercase__max_len(input: TokenStream) -> TokenStream { - let expr: syn::ExprMatch = syn::parse_macro_input!(input); - let strings = expr - .arms - .iter() - .flat_map(|arm| match arm.pat { - syn::Pat::Or(ref p) => p.cases.iter().collect(), - ref p => vec![p], - }) - .filter_map(|pattern| { - let expr = match pattern { - syn::Pat::Lit(expr) => expr, - syn::Pat::Wild(_) => return None, - _ => panic!("expected string or wildcard pattern, got {:?}", pattern), - }; - match *expr.expr { - syn::Expr::Lit(syn::ExprLit { - lit: syn::Lit::Str(ref lit), - .. - }) => { - assert_eq!( - lit.value(), - lit.value().to_ascii_lowercase(), - "string patterns must be given in ASCII lowercase" - ); - Some(lit) - } - _ => panic!("expected string pattern, got {:?}", expr), - } - }); - max_len(strings) -} - -/// Input: string literals with no separator -/// -/// Output: a `MAX_LENGTH` constant with the length of the longest string. -#[allow(non_snake_case)] -#[proc_macro] -pub fn cssparser_internal__max_len(input: TokenStream) -> TokenStream { - struct Input(Vec); +pub fn cssparser_internal__match_ignore_ascii_case__support(input: TokenStream) -> TokenStream { + struct Input { + max_length: usize, + } impl syn::parse::Parse for Input { fn parse(input: syn::parse::ParseStream) -> syn::parse::Result { - let mut strings = Vec::new(); + let mut max_length = 0; while !input.is_empty() { - strings.push(input.parse()?) + if input.peek(syn::Token![_]) { + input.parse::().unwrap(); + continue; + } + let lit: syn::LitStr = input.parse()?; + let value = lit.value(); + if value.to_ascii_lowercase() != value { + return Err(syn::Error::new(lit.span(), "must be ASCII-lowercase")); + } + max_length = max_length.max(value.len()); } - Ok(Self(strings)) + Ok(Input { max_length }) } } - let strings: Input = syn::parse_macro_input!(input); - max_len(strings.0.iter()) -} - -fn max_len<'a, I: Iterator>(strings: I) -> TokenStream { - let max_length = strings - .map(|s| s.value().len()) - .max() - .expect("expected at least one string"); - quote::quote!( pub(super) const MAX_LENGTH: usize = #max_length; ).into() + let Input { max_length } = syn::parse_macro_input!(input); + quote::quote!( + pub(super) const MAX_LENGTH: usize = #max_length; + ) + .into() } -/// Input: A type, followed by pairs of string literal keys and expression values. No separator. -/// -/// Output: a rust-phf map, with keys ASCII-lowercased: -/// ```text -/// static MAP: &'static ::cssparser::phf::Map<&'static str, $ValueType> = …; -/// ``` +/// Implementation detail of the `ascii_case_insensitive_phf_map!` macro #[allow(non_snake_case)] #[proc_macro] -pub fn cssparser_internal__phf_map(input: TokenStream) -> TokenStream { +pub fn cssparser_internal__ascii_case_insensitive_phf_map__support( + input: TokenStream, +) -> TokenStream { struct Input { value_type: syn::Type, + max_key_length: usize, keys: Vec, values: Vec, } impl syn::parse::Parse for Input { fn parse(input: syn::parse::ParseStream) -> syn::parse::Result { + let value_type = input.parse()?; + let mut max_key_length = 0; let mut keys = Vec::new(); let mut values = Vec::new(); - let value_type = input.parse()?; while !input.is_empty() { - keys.push(input.parse()?); + let key: syn::LitStr = input.parse()?; + let key_value = key.value(); + max_key_length = max_key_length.max(key_value.len()); + keys.push(syn::LitStr::new( + &key_value.to_ascii_lowercase(), + key.span(), + )); values.push(input.parse()?); } Ok(Input { value_type, + max_key_length, keys, values, }) @@ -111,14 +80,12 @@ pub fn cssparser_internal__phf_map(input: TokenStream) -> TokenStream { let Input { value_type, + max_key_length, keys, values, } = syn::parse_macro_input!(input); - let keys = keys - .iter() - .map(|s| syn::LitStr::new(&s.value().to_ascii_lowercase(), s.span())); - quote::quote!( + pub(super) const MAX_LENGTH: usize = #max_key_length; pub(super) static MAP: Map<&'static str, #value_type> = phf_map! { #( #keys => #values, diff --git a/src/macros.rs b/src/macros.rs index e74019da..91ea92ec 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -33,7 +33,12 @@ use std::mem::MaybeUninit; /// ``` #[macro_export] macro_rules! match_ignore_ascii_case { - ( $input:expr, $( $match_body:tt )* ) => { + ( $input:expr, + $( + $( $pattern: pat )|+ $( if $guard: expr )? => $then: expr + ),+ + $(,)? + ) => { { // This dummy module works around the feature gate // `error[E0658]: procedural macros cannot be expanded to statements` @@ -41,15 +46,17 @@ macro_rules! match_ignore_ascii_case { // rather than expression/statement context, // even though the macro only expands to items. mod cssparser_internal { - $crate::cssparser_internal__assert_ascii_lowercase__max_len! { - match x { $( $match_body )* } + $crate::cssparser_internal__match_ignore_ascii_case__support! { + $( $( $pattern )+ )+ } } cssparser_internal__to_lowercase!($input, cssparser_internal::MAX_LENGTH => lowercase); // "A" is a short string that we know is different for every string pattern, // since we’ve verified that none of them include ASCII upper case letters. match lowercase.unwrap_or("A") { - $( $match_body )* + $( + $( $pattern )|+ $( if $guard )? => $then, + )+ } } }; @@ -91,8 +98,9 @@ macro_rules! ascii_case_insensitive_phf_map { mod cssparser_internal { use $crate::_internal__phf::{Map, phf_map}; #[allow(unused)] use super::*; - $crate::cssparser_internal__max_len!( $( $key )+ ); - $crate::cssparser_internal__phf_map!( $ValueType $( $key $value )+ ); + $crate::cssparser_internal__ascii_case_insensitive_phf_map__support! { + $ValueType $( $key $value )+ + } } cssparser_internal__to_lowercase!(input, cssparser_internal::MAX_LENGTH => lowercase); lowercase.and_then(|s| cssparser_internal::MAP.get(s)) diff --git a/src/tests.rs b/src/tests.rs index 9658521b..e1114eb1 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -942,7 +942,7 @@ impl<'i> AtRuleParser<'i> for JsonParser { "media" | "foo-with-block" => Ok(AtRuleType::WithBlock(prelude)), "charset" => { Err(input.new_error(BasicParseErrorKind::AtRuleInvalid(name.clone()).into())) - } + }, _ => Ok(AtRuleType::WithoutBlock(prelude)), } } @@ -1399,3 +1399,32 @@ fn utf16_columns() { assert_eq!(parser.current_source_location().column, test.1); } } + +#[test] +fn servo_define_css_keyword_enum() { + macro_rules! define_css_keyword_enum { + (pub enum $name:ident { $($variant:ident = $css:expr,)+ }) => { + #[derive(PartialEq, Debug)] + pub enum $name { + $($variant),+ + } + + impl $name { + pub fn from_ident(ident: &str) -> Result<$name, ()> { + match_ignore_ascii_case! { ident, + $($css => Ok($name::$variant),)+ + _ => Err(()) + } + } + } + } + } + define_css_keyword_enum! { + pub enum UserZoom { + Zoom = "zoom", + Fixed = "fixed", + } + } + + assert_eq!(UserZoom::from_ident("fixed"), Ok(UserZoom::Fixed)); +} From ff98a3462cca297914403e945dae10086af4882c Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 22 Oct 2019 16:14:58 +0200 Subject: [PATCH 4/4] Remove support for the heapsize crate --- .travis.yml | 1 - Cargo.toml | 1 - src/color.rs | 6 ------ src/serializer.rs | 3 --- 4 files changed, 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8da4a509..6e6b124b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,6 @@ script: - cargo build --verbose - cargo test --verbose - cargo doc --verbose - - cargo test --features heapsize - cargo test --features dummy_match_byte - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cargo test --features bench; fi - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cargo test --features "bench dummy_match_byte"; fi diff --git a/Cargo.toml b/Cargo.toml index daefa561..00c8d001 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,6 @@ encoding_rs = "0.8" [dependencies] cssparser-macros = {path = "./macros", version = "0.5"} dtoa-short = "0.3" -heapsize = {version = ">= 0.3, < 0.5", optional = true} itoa = "0.4" matches = "0.1" phf = {version = "0.8", features = ["macros"]} diff --git a/src/color.rs b/src/color.rs index 4eb3d95c..f695d5a1 100644 --- a/src/color.rs +++ b/src/color.rs @@ -101,9 +101,6 @@ impl<'de> Deserialize<'de> for RGBA { } } -#[cfg(feature = "heapsize")] -known_heap_size!(0, RGBA); - impl ToCss for RGBA { fn to_css(&self, dest: &mut W) -> fmt::Result where @@ -141,9 +138,6 @@ pub enum Color { RGBA(RGBA), } -#[cfg(feature = "heapsize")] -known_heap_size!(0, Color); - impl ToCss for Color { fn to_css(&self, dest: &mut W) -> fmt::Result where diff --git a/src/serializer.rs b/src/serializer.rs index d7f27044..abd50c3d 100644 --- a/src/serializer.rs +++ b/src/serializer.rs @@ -402,9 +402,6 @@ impl_tocss_for_float!(f64); #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub struct TokenSerializationType(TokenSerializationTypeVariants); -#[cfg(feature = "heapsize")] -known_heap_size!(0, TokenSerializationType); - impl TokenSerializationType { /// Return a value that represents the absence of a token, e.g. before the start of the input. pub fn nothing() -> TokenSerializationType {