Skip to content

Commit b16eb78

Browse files
committed
Use smallvec to avoid heap allocations
1 parent 7843eff commit b16eb78

File tree

8 files changed

+78
-51
lines changed

8 files changed

+78
-51
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ cssparser-macros = "*"
1717
selectors = "*"
1818
indoc = "*"
1919
itertools = "*"
20+
smallvec = "1.7.0"
2021

2122
[build-dependencies]
2223
napi-build = { version = "1" }

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extern crate serde_bytes;
66
extern crate cssparser;
77
extern crate selectors;
88
extern crate itertools;
9+
extern crate smallvec;
910

1011
mod parser;
1112
mod rules;

src/properties/animation.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use cssparser::*;
22
use crate::traits::{Parse, ToCss, PropertyHandler};
3-
use crate::values::{ident::CustomIdent, time::Time, easing::EasingFunction};
3+
use crate::values::{time::Time, easing::EasingFunction};
44
use super::Property;
55
use crate::printer::Printer;
66
use std::fmt::Write;
77
use itertools::izip;
88
use crate::macros::*;
9+
use smallvec::SmallVec;
910

1011
/// https://drafts.csswg.org/css-animations/#animation-name
1112
#[derive(Debug, Clone, PartialEq)]
@@ -197,14 +198,14 @@ impl ToCss for Animation {
197198

198199
#[derive(Default)]
199200
pub struct AnimationHandler {
200-
names: Option<Vec<AnimationName>>,
201-
durations: Option<Vec<Time>>,
202-
timing_functions: Option<Vec<EasingFunction>>,
203-
iteration_counts: Option<Vec<AnimationIterationCount>>,
204-
directions: Option<Vec<AnimationDirection>>,
205-
play_states: Option<Vec<AnimationPlayState>>,
206-
delays: Option<Vec<Time>>,
207-
fill_modes: Option<Vec<AnimationFillMode>>
201+
names: Option<SmallVec<[AnimationName; 1]>>,
202+
durations: Option<SmallVec<[Time; 1]>>,
203+
timing_functions: Option<SmallVec<[EasingFunction; 1]>>,
204+
iteration_counts: Option<SmallVec<[AnimationIterationCount; 1]>>,
205+
directions: Option<SmallVec<[AnimationDirection; 1]>>,
206+
play_states: Option<SmallVec<[AnimationPlayState; 1]>>,
207+
delays: Option<SmallVec<[Time; 1]>>,
208+
fill_modes: Option<SmallVec<[AnimationFillMode; 1]>>
208209
}
209210

210211
impl PropertyHandler for AnimationHandler {

src/properties/background.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::values::{color::CssColor, image::Image};
66
use crate::properties::Property;
77
use itertools::izip;
88
use crate::printer::Printer;
9+
use smallvec::SmallVec;
910

1011
/// https://www.w3.org/TR/css-backgrounds-3/#background-position
1112
#[derive(Debug, Clone, PartialEq)]
@@ -463,14 +464,14 @@ impl ToCss for Background {
463464
#[derive(Default)]
464465
pub struct BackgroundHandler {
465466
color: Option<CssColor>,
466-
images: Option<Vec<Image>>,
467-
x_positions: Option<Vec<HorizontalPosition>>,
468-
y_positions: Option<Vec<VerticalPosition>>,
469-
repeats: Option<Vec<BackgroundRepeat>>,
470-
sizes: Option<Vec<BackgroundSize>>,
471-
attachments: Option<Vec<BackgroundAttachment>>,
472-
origins: Option<Vec<BackgroundBox>>,
473-
clips: Option<Vec<BackgroundBox>>
467+
images: Option<SmallVec<[Image; 1]>>,
468+
x_positions: Option<SmallVec<[HorizontalPosition; 1]>>,
469+
y_positions: Option<SmallVec<[VerticalPosition; 1]>>,
470+
repeats: Option<SmallVec<[BackgroundRepeat; 1]>>,
471+
sizes: Option<SmallVec<[BackgroundSize; 1]>>,
472+
attachments: Option<SmallVec<[BackgroundAttachment; 1]>>,
473+
origins: Option<SmallVec<[BackgroundBox; 1]>>,
474+
clips: Option<SmallVec<[BackgroundBox; 1]>>
474475
}
475476

476477
impl PropertyHandler for BackgroundHandler {

src/properties/font.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::traits::{Parse, ToCss, PropertyHandler};
55
use super::Property;
66
use crate::printer::Printer;
77
use std::fmt::Write;
8+
use smallvec::SmallVec;
89

910
/// https://www.w3.org/TR/2021/WD-css-fonts-4-20210729/#font-weight-prop
1011
#[derive(Debug, Clone, PartialEq)]

src/properties/mod.rs

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,24 @@ use crate::values::{image::*, length::*, rect::*, color::*, time::Time, ident::C
2929
use crate::traits::{Parse, ToCss};
3030
use crate::printer::Printer;
3131
use std::fmt::Write;
32+
use smallvec::{SmallVec, smallvec};
3233

3334
#[derive(Debug, Clone, PartialEq)]
3435
pub 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

255256
impl 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),

src/properties/transition.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use super::Property;
55
use crate::printer::Printer;
66
use std::fmt::Write;
77
use itertools::izip;
8+
use smallvec::SmallVec;
89

910
/// https://www.w3.org/TR/2018/WD-css-transitions-1-20181011/#transition-shorthand-property
1011
#[derive(Debug, Clone, PartialEq)]
@@ -87,10 +88,10 @@ impl ToCss for Transition {
8788

8889
#[derive(Default)]
8990
pub struct TransitionHandler {
90-
properties: Option<Vec<CustomIdent>>,
91-
durations: Option<Vec<Time>>,
92-
delays: Option<Vec<Time>>,
93-
timing_functions: Option<Vec<EasingFunction>>
91+
properties: Option<SmallVec<[CustomIdent; 1]>>,
92+
durations: Option<SmallVec<[Time; 1]>>,
93+
delays: Option<SmallVec<[Time; 1]>>,
94+
timing_functions: Option<SmallVec<[EasingFunction; 1]>>
9495
}
9596

9697
impl PropertyHandler for TransitionHandler {

0 commit comments

Comments
 (0)