@@ -14,36 +14,36 @@ use std::sync::Arc;
14
14
15
15
use HashMap ;
16
16
17
- /// Although it could, String does not implement From<Cow<str>>
18
- pub trait FromCowStr {
19
- fn from_cow_str ( s : Cow < str > ) -> Self ;
20
- }
21
-
22
- impl FromCowStr for String {
23
- fn from_cow_str ( s : Cow < str > ) -> Self {
24
- s. into_owned ( )
25
- }
26
- }
17
+ macro_rules! with_bounds {
18
+ ( [ $( $CommonBounds: tt ) * ] [ $( $FromStr: tt ) * ] ) => {
19
+ fn from_cow_str<T >( cow: Cow <str >) -> T where T : $( $FromStr) * {
20
+ match cow {
21
+ Cow :: Borrowed ( s) => T :: from( s) ,
22
+ Cow :: Owned ( s) => T :: from( s) ,
23
+ }
24
+ }
27
25
28
- impl FromCowStr for :: string_cache:: Atom {
29
- fn from_cow_str ( s : Cow < str > ) -> Self {
30
- s. into ( )
31
- }
32
- }
26
+ fn from_ascii_lowercase<T >( s: & str ) -> T where T : $( $FromStr) * {
27
+ if let Some ( first_uppercase) = s. bytes( ) . position( |byte| byte >= b'A' && byte <= b'Z' ) {
28
+ let mut string = s. to_owned( ) ;
29
+ string[ first_uppercase..] . make_ascii_lowercase( ) ;
30
+ T :: from( string)
31
+ } else {
32
+ T :: from( s)
33
+ }
34
+ }
33
35
34
- macro_rules! with_bounds {
35
- ( $( $CommonBounds: tt ) * ) => {
36
36
/// This trait allows to define the parser implementation in regards
37
37
/// of pseudo-classes/elements
38
38
pub trait SelectorImpl : Sized + Debug {
39
- type AttrValue : $( $CommonBounds) * + Display + FromCowStr ;
40
- type Identifier : $( $CommonBounds) * + Display + FromCowStr + BloomHash ;
41
- type ClassName : $( $CommonBounds) * + Display + FromCowStr + BloomHash ;
42
- type LocalName : $( $CommonBounds) * + Display + FromCowStr + BloomHash
39
+ type AttrValue : $( $CommonBounds) * + $ ( $FromStr ) * + Display ;
40
+ type Identifier : $( $CommonBounds) * + $ ( $FromStr ) * + Display + BloomHash ;
41
+ type ClassName : $( $CommonBounds) * + $ ( $FromStr ) * + Display + BloomHash ;
42
+ type LocalName : $( $CommonBounds) * + $ ( $FromStr ) * + Display + BloomHash
43
43
+ Borrow <Self :: BorrowedLocalName >;
44
44
type NamespaceUrl : $( $CommonBounds) * + Display + Default + BloomHash
45
45
+ Borrow <Self :: BorrowedNamespaceUrl >;
46
- type NamespacePrefix : $( $CommonBounds) * + Display + Default + FromCowStr ;
46
+ type NamespacePrefix : $( $CommonBounds) * + $ ( $FromStr ) * + Display + Default ;
47
47
type BorrowedNamespaceUrl : ?Sized + Eq ;
48
48
type BorrowedLocalName : ?Sized + Eq + Hash ;
49
49
@@ -88,7 +88,10 @@ macro_rules! with_bounds {
88
88
89
89
macro_rules! with_heap_size_bound {
90
90
( $( $HeapSizeOf: tt ) * ) => {
91
- with_bounds!( Clone + Eq + Hash $( $HeapSizeOf) * ) ;
91
+ with_bounds! {
92
+ [ Clone + Eq + Hash $( $HeapSizeOf) * ]
93
+ [ From <String > + for <' a> From <& ' a str >]
94
+ }
92
95
}
93
96
}
94
97
@@ -722,8 +725,8 @@ fn parse_type_selector<Impl: SelectorImpl>(context: &ParserContext<Impl>, input:
722
725
match local_name {
723
726
Some ( name) => {
724
727
compound_selector. push ( SimpleSelector :: LocalName ( LocalName {
725
- lower_name : Impl :: LocalName :: from_cow_str ( name. to_ascii_lowercase ( ) . into ( ) ) ,
726
- name : Impl :: LocalName :: from_cow_str ( name) ,
728
+ lower_name : from_ascii_lowercase ( & name) ,
729
+ name : from_cow_str ( name) ,
727
730
} ) )
728
731
}
729
732
None => ( ) ,
@@ -777,7 +780,7 @@ fn parse_qualified_name<'i, 't, Impl: SelectorImpl>
777
780
let position = input. position ( ) ;
778
781
match input. next_including_whitespace ( ) {
779
782
Ok ( Token :: Delim ( '|' ) ) => {
780
- let prefix = Impl :: NamespacePrefix :: from_cow_str ( value) ;
783
+ let prefix = from_cow_str ( value) ;
781
784
let result = context. namespace_prefixes . get ( & prefix) ;
782
785
let url = try!( result. ok_or ( ( ) ) ) ;
783
786
explicit_namespace ( input, NamespaceConstraint :: Specific ( Namespace {
@@ -827,13 +830,13 @@ fn parse_attribute_selector<Impl: SelectorImpl>(context: &ParserContext<Impl>, i
827
830
Some ( ( _, None ) ) => unreachable ! ( ) ,
828
831
Some ( ( namespace, Some ( local_name) ) ) => AttrSelector {
829
832
namespace : namespace,
830
- lower_name : Impl :: LocalName :: from_cow_str ( local_name. to_ascii_lowercase ( ) . into ( ) ) ,
831
- name : Impl :: LocalName :: from_cow_str ( local_name) ,
833
+ lower_name : from_ascii_lowercase ( & local_name) ,
834
+ name : from_cow_str ( local_name) ,
832
835
} ,
833
836
} ;
834
837
835
838
fn parse_value < Impl : SelectorImpl > ( input : & mut Parser ) -> Result < Impl :: AttrValue , ( ) > {
836
- Ok ( Impl :: AttrValue :: from_cow_str ( try!( input. expect_ident_or_string ( ) ) ) )
839
+ Ok ( from_cow_str ( try!( input. expect_ident_or_string ( ) ) ) )
837
840
}
838
841
// TODO: deal with empty value or value containing whitespace (see spec)
839
842
match input. next ( ) {
@@ -991,13 +994,13 @@ fn parse_one_simple_selector<Impl: SelectorImpl>(context: &ParserContext<Impl>,
991
994
let start_position = input. position ( ) ;
992
995
match input. next_including_whitespace ( ) {
993
996
Ok ( Token :: IDHash ( id) ) => {
994
- let id = SimpleSelector :: ID ( Impl :: Identifier :: from_cow_str ( id) ) ;
997
+ let id = SimpleSelector :: ID ( from_cow_str ( id) ) ;
995
998
Ok ( Some ( SimpleSelectorParseResult :: SimpleSelector ( id) ) )
996
999
}
997
1000
Ok ( Token :: Delim ( '.' ) ) => {
998
1001
match input. next_including_whitespace ( ) {
999
1002
Ok ( Token :: Ident ( class) ) => {
1000
- let class = SimpleSelector :: Class ( Impl :: ClassName :: from_cow_str ( class) ) ;
1003
+ let class = SimpleSelector :: Class ( from_cow_str ( class) ) ;
1001
1004
Ok ( Some ( SimpleSelectorParseResult :: SimpleSelector ( class) ) )
1002
1005
}
1003
1006
_ => Err ( ( ) ) ,
0 commit comments