@@ -29,23 +29,24 @@ use crate::values::{image::*, length::*, rect::*, color::*, time::Time, ident::C
2929use crate :: traits:: { Parse , ToCss } ;
3030use crate :: printer:: Printer ;
3131use std:: fmt:: Write ;
32+ use smallvec:: { SmallVec , smallvec} ;
3233
3334#[ derive( Debug , Clone , PartialEq ) ]
3435pub enum Property {
3536 BackgroundColor ( CssColor ) ,
36- BackgroundImage ( Vec < Image > ) ,
37- BackgroundPositionX ( Vec < HorizontalPosition > ) ,
38- BackgroundPositionY ( Vec < VerticalPosition > ) ,
39- BackgroundPosition ( Vec < BackgroundPosition > ) ,
40- BackgroundSize ( Vec < BackgroundSize > ) ,
41- BackgroundRepeat ( Vec < BackgroundRepeat > ) ,
42- BackgroundAttachment ( Vec < BackgroundAttachment > ) ,
43- BackgroundClip ( Vec < BackgroundBox > ) ,
44- BackgroundOrigin ( Vec < BackgroundBox > ) ,
37+ BackgroundImage ( SmallVec < [ Image ; 1 ] > ) ,
38+ BackgroundPositionX ( SmallVec < [ HorizontalPosition ; 1 ] > ) ,
39+ BackgroundPositionY ( SmallVec < [ VerticalPosition ; 1 ] > ) ,
40+ BackgroundPosition ( SmallVec < [ BackgroundPosition ; 1 ] > ) ,
41+ BackgroundSize ( SmallVec < [ BackgroundSize ; 1 ] > ) ,
42+ BackgroundRepeat ( SmallVec < [ BackgroundRepeat ; 1 ] > ) ,
43+ BackgroundAttachment ( SmallVec < [ BackgroundAttachment ; 1 ] > ) ,
44+ BackgroundClip ( SmallVec < [ BackgroundBox ; 1 ] > ) ,
45+ BackgroundOrigin ( SmallVec < [ BackgroundBox ; 1 ] > ) ,
4546 // BackgroundBlendMode
46- Background ( Vec < Background > ) ,
47+ Background ( SmallVec < [ Background ; 1 ] > ) ,
4748
48- BoxShadow ( Vec < BoxShadow > ) ,
49+ BoxShadow ( SmallVec < [ BoxShadow ; 1 ] > ) ,
4950 Opacity ( AlphaValue ) ,
5051
5152 Color ( CssColor ) ,
@@ -235,36 +236,55 @@ pub enum Property {
235236 LineHeight ( LineHeight ) ,
236237 Font ( Font ) ,
237238
238- TransitionProperty ( Vec < CustomIdent > ) ,
239- TransitionDuration ( Vec < Time > ) ,
240- TransitionDelay ( Vec < Time > ) ,
241- TransitionTimingFunction ( Vec < EasingFunction > ) ,
242- Transition ( Vec < Transition > ) ,
239+ TransitionProperty ( SmallVec < [ CustomIdent ; 1 ] > ) ,
240+ TransitionDuration ( SmallVec < [ Time ; 1 ] > ) ,
241+ TransitionDelay ( SmallVec < [ Time ; 1 ] > ) ,
242+ TransitionTimingFunction ( SmallVec < [ EasingFunction ; 1 ] > ) ,
243+ Transition ( SmallVec < [ Transition ; 1 ] > ) ,
243244
244- AnimationName ( Vec < AnimationName > ) ,
245- AnimationDuration ( Vec < Time > ) ,
246- AnimationTimingFunction ( Vec < EasingFunction > ) ,
247- AnimationIterationCount ( Vec < AnimationIterationCount > ) ,
248- AnimationDirection ( Vec < AnimationDirection > ) ,
249- AnimationPlayState ( Vec < AnimationPlayState > ) ,
250- AnimationDelay ( Vec < Time > ) ,
251- AnimationFillMode ( Vec < AnimationFillMode > ) ,
252- Animation ( Vec < Animation > )
245+ AnimationName ( SmallVec < [ AnimationName ; 1 ] > ) ,
246+ AnimationDuration ( SmallVec < [ Time ; 1 ] > ) ,
247+ AnimationTimingFunction ( SmallVec < [ EasingFunction ; 1 ] > ) ,
248+ AnimationIterationCount ( SmallVec < [ AnimationIterationCount ; 1 ] > ) ,
249+ AnimationDirection ( SmallVec < [ AnimationDirection ; 1 ] > ) ,
250+ AnimationPlayState ( SmallVec < [ AnimationPlayState ; 1 ] > ) ,
251+ AnimationDelay ( SmallVec < [ Time ; 1 ] > ) ,
252+ AnimationFillMode ( SmallVec < [ AnimationFillMode ; 1 ] > ) ,
253+ Animation ( SmallVec < [ Animation ; 1 ] > )
253254}
254255
255256impl Property {
256257 pub fn parse < ' i , ' t > ( name : CowRcStr < ' i > , input : & mut Parser < ' i , ' t > ) -> Result < Self , ParseError < ' i , ( ) > > {
257258 macro_rules! property {
259+ // font-family is special because it uses Vec rather than SmallVec
260+ // It's likely that there will be more than one font family vs other
261+ // properties where only one is the common case.
262+ ( FontFamily , $type: ident) => {
263+ if let Ok ( c) = input. parse_comma_separated( |input| $type:: parse( input) ) {
264+ return Ok ( Property :: FontFamily ( c) )
265+ }
266+ } ;
258267 ( $property: ident, $type: ident) => {
259268 if let Ok ( c) = $type:: parse( input) {
260269 return Ok ( Property :: $property( c) )
261270 }
262271 } ;
263- ( $property: ident, $type: ident, $multi: expr) => {
264- if let Ok ( c) = input. parse_comma_separated( |input| $type:: parse( input) ) {
265- return Ok ( Property :: $property( c) )
272+ ( $property: ident, $type: ident, $multi: expr) => { {
273+ // Copied from cssparser `parse_comma_separated` but using SmallVec instead of Vec.
274+ let mut values = smallvec![ ] ;
275+ loop {
276+ input. skip_whitespace( ) ; // Unnecessary for correctness, but may help try() in parse_one rewind less.
277+ match input. parse_until_before( Delimiter :: Comma , & mut $type:: parse) {
278+ Ok ( v) => values. push( v) ,
279+ Err ( _) => break
280+ }
281+ match input. next( ) {
282+ Err ( _) => return Ok ( Property :: $property( values) ) ,
283+ Ok ( & Token :: Comma ) => continue ,
284+ Ok ( _) => unreachable!( ) ,
285+ }
266286 }
267- }
287+ } } ;
268288 }
269289
270290 let state = input. state ( ) ;
@@ -436,7 +456,7 @@ impl Property {
436456 "font-weight" => property ! ( FontWeight , FontWeight ) ,
437457 "font-size" => property ! ( FontSize , FontSize ) ,
438458 "font-stretch" => property ! ( FontStretch , FontStretch ) ,
439- "font-family" => property ! ( FontFamily , FontFamily , true ) ,
459+ "font-family" => property ! ( FontFamily , FontFamily ) ,
440460 "font-style" => property ! ( FontStyle , FontStyle ) ,
441461 "font-variant-caps" => property ! ( FontVariantCaps , FontVariantCaps ) ,
442462 "line-height" => property ! ( LineHeight , LineHeight ) ,
0 commit comments