use super::prelude::*;
use crate::{CalcableValue, Percentage};
#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
#[derive(csskit_derives::NodeWithMetadata)]
pub enum EasingFunction<'a> {
#[cfg_attr(feature = "visitable", visit(skip))]
#[atom(CssAtomSet::Linear)]
Linear(T![Ident]),
#[cfg_attr(feature = "visitable", visit(skip))]
#[atom(CssAtomSet::Ease)]
Ease(T![Ident]),
#[cfg_attr(feature = "visitable", visit(skip))]
#[atom(CssAtomSet::EaseIn)]
EaseIn(T![Ident]),
#[cfg_attr(feature = "visitable", visit(skip))]
#[atom(CssAtomSet::EaseOut)]
EaseOut(T![Ident]),
#[cfg_attr(feature = "visitable", visit(skip))]
#[atom(CssAtomSet::EaseInOut)]
EaseInOut(T![Ident]),
#[cfg_attr(feature = "visitable", visit(skip))]
#[atom(CssAtomSet::StepStart)]
StepStart(T![Ident]),
#[cfg_attr(feature = "visitable", visit(skip))]
#[atom(CssAtomSet::StepEnd)]
StepEnd(T![Ident]),
#[atom(CssAtomSet::Linear)]
LinearFunction(LinearFunction<'a>),
#[atom(CssAtomSet::CubicBezier)]
CubicBezierFunction(CubicBezierFunction<'a>),
#[atom(CssAtomSet::Steps)]
StepsFunction(StepsFunction<'a>),
}
#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
#[derive(csskit_derives::NodeWithMetadata)]
pub struct LinearFunction<'a> {
#[atom(CssAtomSet::Linear)]
pub name: T![Function],
pub params: CommaSeparated<'a, LinearFunctionParams<'a>>,
#[semantic_eq(skip)]
pub close: T![')'],
}
#[derive(Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
#[derive(csskit_derives::NodeWithMetadata)]
pub struct LinearFunctionParams<'a>(
CalcableValue<'a, T![Number]>,
Option<CalcableValue<'a, Percentage>>,
Option<CalcableValue<'a, Percentage>>,
);
impl<'a> Parse<'a> for LinearFunctionParams<'a> {
fn parse<I>(p: &mut Parser<'a, I>) -> ParserResult<Self>
where
I: Iterator<Item = Cursor> + Clone,
{
let mut num = p.parse_if_peek::<CalcableValue<T![Number]>>()?;
let percent = p.parse_if_peek::<CalcableValue<Percentage>>()?;
let percent2 = p.parse_if_peek::<CalcableValue<Percentage>>()?;
if num.is_none() {
num = Some(p.parse::<CalcableValue<T![Number]>>()?);
}
Ok(Self(num.unwrap(), percent, percent2))
}
}
#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
#[derive(csskit_derives::NodeWithMetadata)]
pub struct CubicBezierFunction<'a> {
#[atom(CssAtomSet::CubicBezier)]
pub name: T![Function],
pub params: CubicBezierFunctionParams<'a>,
#[semantic_eq(skip)]
pub close: T![')'],
}
#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
pub struct CubicBezierFunctionParams<'a> {
x1: CalcableValue<'a, T![Number]>,
#[semantic_eq(skip)]
c1: Option<T![,]>,
x2: CalcableValue<'a, T![Number]>,
#[semantic_eq(skip)]
c2: Option<T![,]>,
y1: CalcableValue<'a, T![Number]>,
#[semantic_eq(skip)]
c3: Option<T![,]>,
y2: CalcableValue<'a, T![Number]>,
}
#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
#[derive(csskit_derives::NodeWithMetadata)]
pub struct StepsFunction<'a> {
#[atom(CssAtomSet::Steps)]
pub name: T![Function],
pub params: StepsFunctionParams<'a>,
#[semantic_eq(skip)]
pub close: T![')'],
}
#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
pub struct StepsFunctionParams<'a>(CalcableValue<'a, CSSInt>, #[semantic_eq(skip)] Option<T![,]>, Option<StepPosition>);
#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
pub enum StepPosition {
#[atom(CssAtomSet::JumpStart)]
JumpStart(T![Ident]),
#[atom(CssAtomSet::JumpEnd)]
JumpEnd(T![Ident]),
#[atom(CssAtomSet::JumpNone)]
JumpNone(T![Ident]),
#[atom(CssAtomSet::JumpBoth)]
JumpBoth(T![Ident]),
#[atom(CssAtomSet::Start)]
Start(T![Ident]),
#[atom(CssAtomSet::End)]
End(T![Ident]),
}
#[cfg(test)]
mod tests {
use super::*;
use crate::CssAtomSet;
use css_parse::{assert_parse, assert_parse_error, assert_peek_false};
#[test]
fn size_test() {
assert_eq!(std::mem::size_of::<EasingFunction>(), 168);
}
#[test]
fn test_writes() {
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "ease-in-out");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "linear(0,1)");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "linear(0,0.25,1)");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "linear(0,0.5 25% 75%,1)");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "cubic-bezier(0.25,0.1,0.25,1)");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "cubic-bezier(0.1,-0.6,0.2,0)");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "cubic-bezier(0,0,1,1)");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "steps(4,end)");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "steps(10,jump-both)");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "linear(0,0.25,1)");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "cubic-bezier(0.1 -0.6 0.2 0)");
}
#[test]
fn test_substitution() {
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "linear(var(--a),1)");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "cubic-bezier(calc(0.1 + 0.1),0.1,0.25,var(--y))");
assert_parse!(CssAtomSet::ATOMS, EasingFunction, "steps(calc(2 + 2),end)");
}
#[test]
fn test_errors() {
assert_peek_false!(CssAtomSet::ATOMS, EasingFunction, "foo");
assert_parse_error!(CssAtomSet::ATOMS, EasingFunction, "linear()");
assert_parse_error!(CssAtomSet::ATOMS, EasingFunction, "cubic-bezier(0.1, red, 1.0, green)");
}
}