2
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
4
5
- use bloom:: BloomHash ;
6
5
use cssparser:: { Token , Parser , parse_nth, ToCss , serialize_identifier, CssStringWriter } ;
7
6
use std:: ascii:: AsciiExt ;
8
7
use std:: borrow:: { Borrow , Cow } ;
@@ -14,81 +13,92 @@ use std::sync::Arc;
14
13
15
14
use HashMap ;
16
15
17
- /// An empty trait that requires `HeapSizeOf` if the `heap_size` Cargo feature is enabled.
18
- #[ cfg( feature = "heap_size" ) ] pub trait MaybeHeapSizeOf : :: heapsize:: HeapSizeOf { }
19
- #[ cfg( feature = "heap_size" ) ] impl < T : :: heapsize:: HeapSizeOf > MaybeHeapSizeOf for T { }
16
+ macro_rules! with_bounds {
17
+ ( [ $( $CommonBounds: tt ) * ] [ $( $FromStr: tt ) * ] ) => {
18
+ fn from_cow_str<T >( cow: Cow <str >) -> T where T : $( $FromStr) * {
19
+ match cow {
20
+ Cow :: Borrowed ( s) => T :: from( s) ,
21
+ Cow :: Owned ( s) => T :: from( s) ,
22
+ }
23
+ }
20
24
21
- /// An empty trait that requires `HeapSizeOf` if the `heap_size` Cargo feature is enabled.
22
- #[ cfg( not( feature = "heap_size" ) ) ] pub trait MaybeHeapSizeOf { }
23
- #[ cfg( not( feature = "heap_size" ) ) ] impl < T > MaybeHeapSizeOf for T { }
25
+ fn from_ascii_lowercase<T >( s: & str ) -> T where T : $( $FromStr) * {
26
+ if let Some ( first_uppercase) = s. bytes( ) . position( |byte| byte >= b'A' && byte <= b'Z' ) {
27
+ let mut string = s. to_owned( ) ;
28
+ string[ first_uppercase..] . make_ascii_lowercase( ) ;
29
+ T :: from( string)
30
+ } else {
31
+ T :: from( s)
32
+ }
33
+ }
24
34
25
- /// Although it could, String does not implement From<Cow<str>>
26
- pub trait FromCowStr {
27
- fn from_cow_str ( s : Cow < str > ) -> Self ;
28
- }
35
+ /// This trait allows to define the parser implementation in regards
36
+ /// of pseudo-classes/elements
37
+ pub trait SelectorImpl : Sized + Debug {
38
+ type AttrValue : $( $CommonBounds) * + $( $FromStr) * + Display ;
39
+ type Identifier : $( $CommonBounds) * + $( $FromStr) * + Display ;
40
+ type ClassName : $( $CommonBounds) * + $( $FromStr) * + Display ;
41
+ type LocalName : $( $CommonBounds) * + $( $FromStr) * + Display
42
+ + Borrow <Self :: BorrowedLocalName >;
43
+ type NamespaceUrl : $( $CommonBounds) * + Display + Default
44
+ + Borrow <Self :: BorrowedNamespaceUrl >;
45
+ type NamespacePrefix : $( $CommonBounds) * + $( $FromStr) * + Display + Default ;
46
+ type BorrowedNamespaceUrl : ?Sized + Eq ;
47
+ type BorrowedLocalName : ?Sized + Eq + Hash ;
48
+
49
+ /// non tree-structural pseudo-classes
50
+ /// (see: https://drafts.csswg.org/selectors/#structural-pseudos)
51
+ type NonTSPseudoClass : $( $CommonBounds) * + Sized + ToCss ;
52
+
53
+ /// pseudo-elements
54
+ type PseudoElement : $( $CommonBounds) * + Sized + ToCss ;
55
+
56
+ /// Declares if the following "attribute exists" selector is considered
57
+ /// "common" enough to be shareable. If that's not the case, when matching
58
+ /// over an element, the relation
59
+ /// AFFECTED_BY_NON_COMMON_STYLE_AFFECTING_ATTRIBUTE would be set.
60
+ fn attr_exists_selector_is_shareable( _attr_selector: & AttrSelector <Self >) -> bool {
61
+ false
62
+ }
29
63
30
- impl FromCowStr for String {
31
- fn from_cow_str ( s : Cow < str > ) -> Self {
32
- s. into_owned ( )
33
- }
34
- }
64
+ /// Declares if the following "equals" attribute selector is considered
65
+ /// "common" enough to be shareable.
66
+ fn attr_equals_selector_is_shareable( _attr_selector: & AttrSelector <Self >,
67
+ _value: & Self :: AttrValue ) -> bool {
68
+ false
69
+ }
35
70
36
- impl FromCowStr for :: string_cache:: Atom {
37
- fn from_cow_str ( s : Cow < str > ) -> Self {
38
- s. into ( )
71
+ /// This function can return an "Err" pseudo-element in order to support CSS2.1
72
+ /// pseudo-elements.
73
+ fn parse_non_ts_pseudo_class( _context: & ParserContext <Self >,
74
+ _name: & str )
75
+ -> Result <Self :: NonTSPseudoClass , ( ) > { Err ( ( ) ) }
76
+
77
+ fn parse_non_ts_functional_pseudo_class( _context: & ParserContext <Self >,
78
+ _name: & str ,
79
+ _arguments: & mut Parser )
80
+ -> Result <Self :: NonTSPseudoClass , ( ) > { Err ( ( ) ) }
81
+ fn parse_pseudo_element( _context: & ParserContext <Self >,
82
+ _name: & str )
83
+ -> Result <Self :: PseudoElement , ( ) > { Err ( ( ) ) }
84
+ }
39
85
}
40
86
}
41
87
42
- /// This trait allows to define the parser implementation in regards
43
- /// of pseudo-classes/elements
44
- pub trait SelectorImpl : Sized + Debug {
45
- type AttrValue : Clone + Display + MaybeHeapSizeOf + Eq + FromCowStr + Hash ;
46
- type Identifier : Clone + Display + MaybeHeapSizeOf + Eq + FromCowStr + Hash + BloomHash ;
47
- type ClassName : Clone + Display + MaybeHeapSizeOf + Eq + FromCowStr + Hash + BloomHash ;
48
- type LocalName : Clone + Display + MaybeHeapSizeOf + Eq + FromCowStr + Hash + BloomHash
49
- + Borrow < Self :: BorrowedLocalName > ;
50
- type NamespaceUrl : Clone + Display + MaybeHeapSizeOf + Eq + Default + Hash + BloomHash
51
- + Borrow < Self :: BorrowedNamespaceUrl > ;
52
- type NamespacePrefix : Clone + Display + MaybeHeapSizeOf + Eq + Default + Hash + FromCowStr ;
53
- type BorrowedNamespaceUrl : ?Sized + Eq ;
54
- type BorrowedLocalName : ?Sized + Eq + Hash ;
55
-
56
- /// Declares if the following "attribute exists" selector is considered
57
- /// "common" enough to be shareable. If that's not the case, when matching
58
- /// over an element, the relation
59
- /// AFFECTED_BY_NON_COMMON_STYLE_AFFECTING_ATTRIBUTE would be set.
60
- fn attr_exists_selector_is_shareable ( _attr_selector : & AttrSelector < Self > ) -> bool {
61
- false
88
+ macro_rules! with_heap_size_bound {
89
+ ( $( $HeapSizeOf: tt ) * ) => {
90
+ with_bounds! {
91
+ [ Clone + Eq + Hash $( $HeapSizeOf) * ]
92
+ [ From <String > + for <' a> From <& ' a str >]
93
+ }
62
94
}
95
+ }
63
96
64
- /// Declares if the following "equals" attribute selector is considered
65
- /// "common" enough to be shareable.
66
- fn attr_equals_selector_is_shareable ( _attr_selector : & AttrSelector < Self > ,
67
- _value : & Self :: AttrValue ) -> bool {
68
- false
69
- }
97
+ #[ cfg( feature = "heap_size" ) ]
98
+ with_heap_size_bound ! ( + :: heapsize:: HeapSizeOf ) ;
70
99
71
- /// non tree-structural pseudo-classes
72
- /// (see: https://drafts.csswg.org/selectors/#structural-pseudos)
73
- type NonTSPseudoClass : Clone + Eq + Hash + MaybeHeapSizeOf + PartialEq + Sized + ToCss ;
74
-
75
- /// This function can return an "Err" pseudo-element in order to support CSS2.1
76
- /// pseudo-elements.
77
- fn parse_non_ts_pseudo_class ( _context : & ParserContext < Self > ,
78
- _name : & str )
79
- -> Result < Self :: NonTSPseudoClass , ( ) > { Err ( ( ) ) }
80
-
81
- fn parse_non_ts_functional_pseudo_class ( _context : & ParserContext < Self > ,
82
- _name : & str ,
83
- _arguments : & mut Parser )
84
- -> Result < Self :: NonTSPseudoClass , ( ) > { Err ( ( ) ) }
85
-
86
- /// pseudo-elements
87
- type PseudoElement : Sized + PartialEq + Eq + Clone + Hash + MaybeHeapSizeOf + ToCss ;
88
- fn parse_pseudo_element ( _context : & ParserContext < Self > ,
89
- _name : & str )
90
- -> Result < Self :: PseudoElement , ( ) > { Err ( ( ) ) }
91
- }
100
+ #[ cfg( not( feature = "heap_size" ) ) ]
101
+ with_heap_size_bound ! ( ) ;
92
102
93
103
pub struct ParserContext < Impl : SelectorImpl > {
94
104
pub in_user_agent_stylesheet : bool ,
@@ -714,8 +724,8 @@ fn parse_type_selector<Impl: SelectorImpl>(context: &ParserContext<Impl>, input:
714
724
match local_name {
715
725
Some ( name) => {
716
726
compound_selector. push ( SimpleSelector :: LocalName ( LocalName {
717
- lower_name : Impl :: LocalName :: from_cow_str ( name. to_ascii_lowercase ( ) . into ( ) ) ,
718
- name : Impl :: LocalName :: from_cow_str ( name) ,
727
+ lower_name : from_ascii_lowercase ( & name) ,
728
+ name : from_cow_str ( name) ,
719
729
} ) )
720
730
}
721
731
None => ( ) ,
@@ -769,7 +779,7 @@ fn parse_qualified_name<'i, 't, Impl: SelectorImpl>
769
779
let position = input. position ( ) ;
770
780
match input. next_including_whitespace ( ) {
771
781
Ok ( Token :: Delim ( '|' ) ) => {
772
- let prefix = Impl :: NamespacePrefix :: from_cow_str ( value) ;
782
+ let prefix = from_cow_str ( value) ;
773
783
let result = context. namespace_prefixes . get ( & prefix) ;
774
784
let url = try!( result. ok_or ( ( ) ) ) ;
775
785
explicit_namespace ( input, NamespaceConstraint :: Specific ( Namespace {
@@ -819,13 +829,13 @@ fn parse_attribute_selector<Impl: SelectorImpl>(context: &ParserContext<Impl>, i
819
829
Some ( ( _, None ) ) => unreachable ! ( ) ,
820
830
Some ( ( namespace, Some ( local_name) ) ) => AttrSelector {
821
831
namespace : namespace,
822
- lower_name : Impl :: LocalName :: from_cow_str ( local_name. to_ascii_lowercase ( ) . into ( ) ) ,
823
- name : Impl :: LocalName :: from_cow_str ( local_name) ,
832
+ lower_name : from_ascii_lowercase ( & local_name) ,
833
+ name : from_cow_str ( local_name) ,
824
834
} ,
825
835
} ;
826
836
827
837
fn parse_value < Impl : SelectorImpl > ( input : & mut Parser ) -> Result < Impl :: AttrValue , ( ) > {
828
- Ok ( Impl :: AttrValue :: from_cow_str ( try!( input. expect_ident_or_string ( ) ) ) )
838
+ Ok ( from_cow_str ( try!( input. expect_ident_or_string ( ) ) ) )
829
839
}
830
840
// TODO: deal with empty value or value containing whitespace (see spec)
831
841
match input. next ( ) {
@@ -983,13 +993,13 @@ fn parse_one_simple_selector<Impl: SelectorImpl>(context: &ParserContext<Impl>,
983
993
let start_position = input. position ( ) ;
984
994
match input. next_including_whitespace ( ) {
985
995
Ok ( Token :: IDHash ( id) ) => {
986
- let id = SimpleSelector :: ID ( Impl :: Identifier :: from_cow_str ( id) ) ;
996
+ let id = SimpleSelector :: ID ( from_cow_str ( id) ) ;
987
997
Ok ( Some ( SimpleSelectorParseResult :: SimpleSelector ( id) ) )
988
998
}
989
999
Ok ( Token :: Delim ( '.' ) ) => {
990
1000
match input. next_including_whitespace ( ) {
991
1001
Ok ( Token :: Ident ( class) ) => {
992
- let class = SimpleSelector :: Class ( Impl :: ClassName :: from_cow_str ( class) ) ;
1002
+ let class = SimpleSelector :: Class ( from_cow_str ( class) ) ;
993
1003
Ok ( Some ( SimpleSelectorParseResult :: SimpleSelector ( class) ) )
994
1004
}
995
1005
_ => Err ( ( ) ) ,
0 commit comments