[librsvg: 3/12] Update to selectors 0.23.0 and cssparser 0.28.0 together




commit 8a836c9e9fbc4a200a09f3367a95729e6d381f99
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Dec 8 10:47:18 2021 -0600

    Update to selectors 0.23.0 and cssparser 0.28.0 together
    
    This is the latest version of selectors.
    This is not the latest version of cssparser; the latest is 0.20.
    
    However, selectors 0.23.0 depends on cssparser's traits, so they need to be
    compatible versions.  This is why we only update to cssparser 0.28.0.
    
    This commit is mostly about adjusting to the API changes in selectors 0.23.0:
    
    * Several of the associated types in the selectors::SelectorImpl trait
    now must implement cssparser::ToCss instead of
    fmt::Display (apparently to save allocations).
    
    This requires us to use newtypes around the lower-level types we were
    using for those associated types:
    
      struct AttributeValue(String);
      struct Identifier(markup5ever::LocalName);
      struct LocalName(markup5ever::LocalName);
      struct NamespacePrefix(markup5ever::Prefix);
    
    Each of those newtypes implements From<&str> and ToCss.  Specific
    types have more specific requirements, like `impl AsRef<str> for AttributeValue`.
    
    Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/641>

 Cargo.lock |  16 ++-----
 Cargo.toml |   4 +-
 src/css.rs | 157 +++++++++++++++++++++++++++++++++++++++++++++++--------------
 3 files changed, 128 insertions(+), 49 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 0885a011..21378d2b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -332,9 +332,9 @@ dependencies = [
 
 [[package]]
 name = "cssparser"
-version = "0.27.2"
+version = "0.28.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a"
+checksum = "1db8599a9761b371751fbf13e076fa03c6e1a78f8c5288e6ab9467f10a2322c1"
 dependencies = [
  "cssparser-macros",
  "dtoa-short",
@@ -1775,22 +1775,20 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
 name = "selectors"
-version = "0.22.0"
+version = "0.23.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe"
+checksum = "fdea87c686be721aab36607728047801ee21561bfdbd6bf0da7ace2536d5879f"
 dependencies = [
  "bitflags",
  "cssparser",
  "derive_more",
  "fxhash",
  "log",
- "matches",
  "phf",
  "phf_codegen",
  "precomputed-hash",
  "servo_arc",
  "smallvec",
- "thin-slice",
 ]
 
 [[package]]
@@ -2104,12 +2102,6 @@ dependencies = [
  "unicode-width",
 ]
 
-[[package]]
-name = "thin-slice"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
-
 [[package]]
 name = "thiserror"
 version = "1.0.30"
diff --git a/Cargo.toml b/Cargo.toml
index daeabfd1..ed5585ec 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -45,7 +45,7 @@ cairo-rs = { version="0.14.0", features=["v1_16", "png", "pdf", "ps", "svg"] }
 cast = "0.3.0"
 chrono = "0.4.0" # rsvg-convert
 clap = "~2.33.0" # rsvg-convert
-cssparser = "0.27.1"
+cssparser = "0.28.0"
 data-url = "0.1"
 encoding = "0.2.33"
 float-cmp = "0.8.0"
@@ -66,7 +66,7 @@ rayon = "1"
 rctree = "0.3.3"
 regex = "1"
 rgb = { version="0.8", features=["argb"] }
-selectors = "0.22.0"
+selectors = "0.23.0"
 string_cache = "0.8.0"
 tinyvec = { version = "1.2.0", features = ["alloc"] }
 url = "2"
diff --git a/src/css.rs b/src/css.rs
index 842cc717..3871d9ba 100644
--- a/src/css.rs
+++ b/src/css.rs
@@ -75,12 +75,12 @@
 
 use cssparser::{
     self, match_ignore_ascii_case, parse_important, AtRuleParser, AtRuleType, BasicParseErrorKind,
-    CowRcStr, DeclarationListParser, DeclarationParser, Parser, ParserInput, QualifiedRuleParser,
-    RuleListParser, SourceLocation, ToCss, _cssparser_internal_to_lowercase,
+    CowRcStr, DeclarationListParser, DeclarationParser, Parser, ParserInput, ParserState,
+    QualifiedRuleParser, RuleListParser, SourceLocation, ToCss, _cssparser_internal_to_lowercase,
 };
 use data_url::mime::Mime;
 use language_tags::LanguageTag;
-use markup5ever::{namespace_url, ns, LocalName, Namespace, Prefix, QualName};
+use markup5ever::{self, namespace_url, ns, Namespace, QualName};
 use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint};
 use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode, QuirksMode};
 use selectors::{OpaqueElement, SelectorImpl, SelectorList};
@@ -123,7 +123,7 @@ impl<'i> DeclarationParser<'i> for DeclParser {
         name: CowRcStr<'i>,
         input: &mut Parser<'i, 't>,
     ) -> Result<Declaration, ParseError<'i>> {
-        let prop_name = QualName::new(None, ns!(), LocalName::from(name.as_ref()));
+        let prop_name = QualName::new(None, ns!(), markup5ever::LocalName::from(name.as_ref()));
         let property = parse_value(&prop_name, input, ParseAs::Property)?;
 
         let important = input.try_parse(parse_important).is_ok();
@@ -276,7 +276,7 @@ impl<'i> QualifiedRuleParser<'i> for RuleParser {
     fn parse_block<'t>(
         &mut self,
         prelude: Self::Prelude,
-        _location: SourceLocation,
+        _start: &ParserState,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self::QualifiedRule, cssparser::ParseError<'i, Self::Error>> {
         let declarations = DeclarationListParser::new(input, DeclParser)
@@ -328,7 +328,7 @@ impl<'i> AtRuleParser<'i> for RuleParser {
     fn rule_without_block(
         &mut self,
         prelude: Self::PreludeNoBlock,
-        _location: SourceLocation,
+        _start: &ParserState,
     ) -> Self::AtRule {
         let AtRulePrelude::Import(url) = prelude;
         Rule::AtRule(AtRule::Import(url))
@@ -374,10 +374,6 @@ impl selectors::parser::NonTSPseudoClass for NonTSPseudoClass {
     fn is_user_action_state(&self) -> bool {
         false
     }
-
-    fn has_zero_specificity(&self) -> bool {
-        false
-    }
 }
 
 /// Dummy type required by the SelectorImpl trait
@@ -401,15 +397,108 @@ impl selectors::parser::PseudoElement for PseudoElement {
 #[derive(Debug, Clone)]
 pub struct Selector;
 
+/// Wrapper for attribute values.
+///
+/// We use a newtype because the associated type Selector::AttrValue
+/// must implement `From<&str>` and `ToCss`, which are foreign traits.
+///
+/// The `derive` requirements come from the `selectors` crate.
+#[derive(Clone, PartialEq, Eq)]
+pub struct AttributeValue(String);
+
+impl From<&str> for AttributeValue {
+    fn from(s: &str) -> AttributeValue {
+        AttributeValue(s.to_owned())
+    }
+}
+
+impl ToCss for AttributeValue {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+    where
+        W: fmt::Write,
+    {
+        use std::fmt::Write;
+
+        write!(cssparser::CssStringWriter::new(dest), "{}", &self.0)
+    }
+}
+
+impl AsRef<str> for AttributeValue {
+    fn as_ref(&self) -> &str {
+        self.0.as_ref()
+    }
+}
+
+/// Wrapper for identifier values.
+///
+/// Used to implement `ToCss` on the `LocalName` foreign type.
+#[derive(Clone, PartialEq, Eq)]
+pub struct Identifier(markup5ever::LocalName);
+
+impl From<&str> for Identifier {
+    fn from(s: &str) -> Identifier {
+        Identifier(markup5ever::LocalName::from(s))
+    }
+}
+
+impl ToCss for Identifier {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+    where
+        W: fmt::Write,
+    {
+        cssparser::serialize_identifier(&self.0, dest)
+    }
+}
+
+/// Wrapper for local names.
+///
+/// Used to implement `ToCss` on the `LocalName` foreign type.
+#[derive(Clone, PartialEq, Eq)]
+pub struct LocalName(markup5ever::LocalName);
+
+impl From<&str> for LocalName {
+    fn from(s: &str) -> LocalName {
+        LocalName(markup5ever::LocalName::from(s))
+    }
+}
+
+impl ToCss for LocalName {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+    where
+        W: fmt::Write,
+    {
+        cssparser::serialize_identifier(&self.0, dest)
+    }
+}
+
+/// Wrapper for namespace prefixes.
+///
+/// Used to implement `ToCss` on the `markup5ever::Prefix` foreign type.
+#[derive(Clone, Default, PartialEq, Eq)]
+pub struct NamespacePrefix(markup5ever::Prefix);
+
+impl From<&str> for NamespacePrefix {
+    fn from(s: &str) -> NamespacePrefix {
+        NamespacePrefix(markup5ever::Prefix::from(s))
+    }
+}
+
+impl ToCss for NamespacePrefix {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+    where
+        W: fmt::Write,
+    {
+        cssparser::serialize_identifier(&self.0, dest)
+    }
+}
+
 impl SelectorImpl for Selector {
     type ExtraMatchingData = ();
-    type AttrValue = String;
-    type Identifier = LocalName;
-    type ClassName = LocalName;
-    type PartName = LocalName;
+    type AttrValue = AttributeValue;
+    type Identifier = Identifier;
     type LocalName = LocalName;
     type NamespaceUrl = Namespace;
-    type NamespacePrefix = Prefix;
+    type NamespacePrefix = NamespacePrefix;
     type BorrowedNamespaceUrl = Namespace;
     type BorrowedLocalName = LocalName;
     type NonTSPseudoClass = NonTSPseudoClass;
@@ -503,7 +592,7 @@ impl selectors::Element for RsvgElement {
     }
 
     fn has_local_name(&self, local_name: &LocalName) -> bool {
-        self.0.borrow_element().element_name().local == *local_name
+        self.0.borrow_element().element_name().local == local_name.0
     }
 
     /// Empty string for no namespace
@@ -520,7 +609,7 @@ impl selectors::Element for RsvgElement {
         &self,
         ns: &NamespaceConstraint<&Namespace>,
         local_name: &LocalName,
-        operation: &AttrSelectorOperation<&String>,
+        operation: &AttrSelectorOperation<&AttributeValue>,
     ) -> bool {
         self.0
             .borrow_element()
@@ -529,9 +618,9 @@ impl selectors::Element for RsvgElement {
             .find(|(attr, _)| {
                 // do we have an attribute that matches the namespace and local_name?
                 match *ns {
-                    NamespaceConstraint::Any => *local_name == attr.local,
+                    NamespaceConstraint::Any => local_name.0 == attr.local,
                     NamespaceConstraint::Specific(ns) => {
-                        QualName::new(None, ns.clone(), local_name.clone()) == *attr
+                        QualName::new(None, ns.clone(), local_name.0.clone()) == *attr
                     }
                 }
             })
@@ -596,37 +685,32 @@ impl selectors::Element for RsvgElement {
         false
     }
 
-    fn has_id(&self, id: &LocalName, case_sensitivity: CaseSensitivity) -> bool {
+    fn has_id(&self, id: &Identifier, case_sensitivity: CaseSensitivity) -> bool {
         self.0
             .borrow_element()
             .get_id()
-            .map(|self_id| case_sensitivity.eq(self_id.as_bytes(), id.as_ref().as_bytes()))
+            .map(|self_id| case_sensitivity.eq(self_id.as_bytes(), id.0.as_bytes()))
             .unwrap_or(false)
     }
 
-    fn has_class(&self, name: &LocalName, case_sensitivity: CaseSensitivity) -> bool {
+    fn has_class(&self, name: &Identifier, case_sensitivity: CaseSensitivity) -> bool {
         self.0
             .borrow_element()
             .get_class()
             .map(|classes| {
                 classes
                     .split_whitespace()
-                    .any(|class| case_sensitivity.eq(class.as_bytes(), name.as_bytes()))
+                    .any(|class| case_sensitivity.eq(class.as_bytes(), name.0.as_bytes()))
             })
             .unwrap_or(false)
     }
 
-    fn exported_part(&self, _name: &LocalName) -> Option<LocalName> {
+    fn imported_part(&self, _name: &Identifier) -> Option<Identifier> {
         // unsupported
         None
     }
 
-    fn imported_part(&self, _name: &LocalName) -> Option<LocalName> {
-        // unsupported
-        None
-    }
-
-    fn is_part(&self, _name: &LocalName) -> bool {
+    fn is_part(&self, _name: &Identifier) -> bool {
         // unsupported
         false
     }
@@ -969,23 +1053,26 @@ mod tests {
         assert!(!a.is_same_type(&b));
         assert!(b.is_same_type(&d));
 
-        assert!(a.has_id(&LocalName::from("a"), CaseSensitivity::AsciiCaseInsensitive));
+        assert!(a.has_id(
+            &Identifier::from("a"),
+            CaseSensitivity::AsciiCaseInsensitive
+        ));
         assert!(!b.has_id(
-            &LocalName::from("foo"),
+            &Identifier::from("foo"),
             CaseSensitivity::AsciiCaseInsensitive
         ));
 
         assert!(d.has_class(
-            &LocalName::from("foo"),
+            &Identifier::from("foo"),
             CaseSensitivity::AsciiCaseInsensitive
         ));
         assert!(d.has_class(
-            &LocalName::from("bar"),
+            &Identifier::from("bar"),
             CaseSensitivity::AsciiCaseInsensitive
         ));
 
         assert!(!a.has_class(
-            &LocalName::from("foo"),
+            &Identifier::from("foo"),
             CaseSensitivity::AsciiCaseInsensitive
         ));
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]