1use super::prelude::*;
2use crate::Percentage;
3
4#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
25#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
26#[derive(csskit_derives::NodeWithMetadata)]
27pub enum EasingFunction<'a> {
28 #[cfg_attr(feature = "visitable", visit(skip))]
29 #[atom(CssAtomSet::Linear)]
30 Linear(T![Ident]),
31 #[cfg_attr(feature = "visitable", visit(skip))]
32 #[atom(CssAtomSet::Ease)]
33 Ease(T![Ident]),
34 #[cfg_attr(feature = "visitable", visit(skip))]
35 #[atom(CssAtomSet::EaseIn)]
36 EaseIn(T![Ident]),
37 #[cfg_attr(feature = "visitable", visit(skip))]
38 #[atom(CssAtomSet::EaseOut)]
39 EaseOut(T![Ident]),
40 #[cfg_attr(feature = "visitable", visit(skip))]
41 #[atom(CssAtomSet::EaseInOut)]
42 EaseInOut(T![Ident]),
43 #[cfg_attr(feature = "visitable", visit(skip))]
44 #[atom(CssAtomSet::StepStart)]
45 StepStart(T![Ident]),
46 #[cfg_attr(feature = "visitable", visit(skip))]
47 #[atom(CssAtomSet::StepEnd)]
48 StepEnd(T![Ident]),
49 #[atom(CssAtomSet::Linear)]
50 LinearFunction(LinearFunction<'a>),
51 #[atom(CssAtomSet::CubicBezier)]
52 CubicBezierFunction(CubicBezierFunction),
53 #[atom(CssAtomSet::Steps)]
54 StepsFunction(StepsFunction),
55}
56
57#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
58#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
59#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
60#[derive(csskit_derives::NodeWithMetadata)]
61pub struct LinearFunction<'a> {
62 #[atom(CssAtomSet::Linear)]
63 pub name: T![Function],
64 pub params: CommaSeparated<'a, LinearFunctionParams>,
65 pub close: T![')'],
66}
67
68#[derive(Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
70#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
71#[derive(csskit_derives::NodeWithMetadata)]
72pub struct LinearFunctionParams(T![Number], Option<Percentage>, Option<Percentage>);
73
74impl<'a> Parse<'a> for LinearFunctionParams {
75 fn parse<I>(p: &mut Parser<'a, I>) -> ParserResult<Self>
76 where
77 I: Iterator<Item = Cursor> + Clone,
78 {
79 let mut num = p.parse_if_peek::<T![Number]>()?;
80 let percent = p.parse_if_peek::<Percentage>()?;
81 let percent2 = p.parse_if_peek::<Percentage>()?;
82 if num.is_none() {
83 num = Some(p.parse::<T![Number]>()?);
84 }
85 Ok(Self(num.unwrap(), percent, percent2))
86 }
87}
88
89#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
90#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
91#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
92#[derive(csskit_derives::NodeWithMetadata)]
93pub struct CubicBezierFunction {
94 #[atom(CssAtomSet::CubicBezier)]
95 pub name: T![Function],
96 pub params: CubicBezierFunctionParams,
97 pub close: T![')'],
98}
99
100#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
101#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
102pub struct CubicBezierFunctionParams {
103 x1: T![Number],
104 c1: Option<T![,]>,
105 x2: T![Number],
106 c2: Option<T![,]>,
107 y1: T![Number],
108 c3: Option<T![,]>,
109 y2: T![Number],
110}
111
112#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
113#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
114#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
115#[derive(csskit_derives::NodeWithMetadata)]
116pub struct StepsFunction {
117 #[atom(CssAtomSet::Steps)]
118 pub name: T![Function],
119 pub params: StepsFunctionParams,
120 pub close: T![')'],
121}
122
123#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
124#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
125pub struct StepsFunctionParams(CSSInt, Option<T![,]>, Option<StepPosition>);
126
127#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
128#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
129pub enum StepPosition {
130 #[atom(CssAtomSet::JumpStart)]
131 JumpStart(T![Ident]),
132 #[atom(CssAtomSet::JumpEnd)]
133 JumpEnd(T![Ident]),
134 #[atom(CssAtomSet::JumpNone)]
135 JumpNone(T![Ident]),
136 #[atom(CssAtomSet::JumpBoth)]
137 JumpBoth(T![Ident]),
138 #[atom(CssAtomSet::Start)]
139 Start(T![Ident]),
140 #[atom(CssAtomSet::End)]
141 End(T![Ident]),
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147 use crate::CssAtomSet;
148 use css_parse::{assert_parse, assert_parse_error};
149
150 #[test]
151 fn size_test() {
152 assert_eq!(std::mem::size_of::<EasingFunction>(), 120);
153 }
154
155 #[test]
156 fn test_writes() {
157 assert_parse!(CssAtomSet::ATOMS, EasingFunction, "ease-in-out");
158 assert_parse!(CssAtomSet::ATOMS, EasingFunction, "linear(0,1)");
159 assert_parse!(CssAtomSet::ATOMS, EasingFunction, "linear(0,0.25,1)");
160 assert_parse!(CssAtomSet::ATOMS, EasingFunction, "linear(0,0.5 25% 75%,1)");
161 assert_parse!(CssAtomSet::ATOMS, EasingFunction, "cubic-bezier(0.25,0.1,0.25,1)");
162 assert_parse!(CssAtomSet::ATOMS, EasingFunction, "cubic-bezier(0.1,-0.6,0.2,0)");
163 assert_parse!(CssAtomSet::ATOMS, EasingFunction, "cubic-bezier(0,0,1,1)");
164 assert_parse!(CssAtomSet::ATOMS, EasingFunction, "steps(4,end)");
165 assert_parse!(CssAtomSet::ATOMS, EasingFunction, "steps(10,jump-both)");
166 assert_parse!(CssAtomSet::ATOMS, EasingFunction, "linear(0,0.25,1)");
167 assert_parse!(CssAtomSet::ATOMS, EasingFunction, "cubic-bezier(0.1 -0.6 0.2 0)");
168 }
169
170 #[test]
171 fn test_errors() {
172 assert_parse_error!(CssAtomSet::ATOMS, EasingFunction, "foo");
173 assert_parse_error!(CssAtomSet::ATOMS, EasingFunction, "linear()");
174 assert_parse_error!(CssAtomSet::ATOMS, EasingFunction, "cubic-bezier(0.1, red, 1.0, green)");
175 }
176}