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