css_ast/types/
single_transition.rs1use css_parse::{Cursor, Parse, Parser, Peek, Result as ParserResult, parse_optionals};
2use csskit_derives::{ToCursors, ToSpan, Visitable};
3
4use crate::{EasingFunction, NoneOr, SingleTransitionProperty, Time, TransitionBehaviorValue};
5
6#[derive(ToCursors, ToSpan, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
10#[visit]
11pub struct SingleTransition<'a> {
12 #[visit(skip)]
13 pub property: Option<NoneOr<SingleTransitionProperty>>,
14 pub duration: Option<Time>,
15 pub easing: Option<EasingFunction<'a>>,
16 pub delay: Option<Time>,
17 #[visit(skip)]
18 pub behavior: Option<TransitionBehaviorValue>,
19}
20
21impl<'a> Peek<'a> for SingleTransition<'a> {
22 fn peek(p: &Parser<'a>, c: Cursor) -> bool {
23 <NoneOr<SingleTransitionProperty>>::peek(p, c) || EasingFunction::peek(p, c) || Time::peek(p, c)
24 }
25}
26
27impl<'a> Parse<'a> for SingleTransition<'a> {
28 fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
29 let (easing, property, duration, delay, behavior) = parse_optionals!(p, easing: EasingFunction, property: NoneOr<SingleTransitionProperty>, duration: Time, delay: Time, behavior: TransitionBehaviorValue);
30 Ok(Self { easing, property, duration, delay, behavior })
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37 use crate::assert_visits;
38 use css_parse::{assert_parse, assert_parse_error};
39
40 type NoneOrSingleTransitionProperty = NoneOr<SingleTransitionProperty>;
41
42 #[test]
43 fn size_test() {
44 assert_eq!(std::mem::size_of::<SingleTransition>(), 192);
45 }
46
47 #[test]
48 fn test_writes() {
49 assert_parse!(NoneOrSingleTransitionProperty, "none", NoneOrSingleTransitionProperty::None(_));
50 assert_parse!(NoneOrSingleTransitionProperty, "all", NoneOrSingleTransitionProperty::Some(_));
51
52 assert_parse!(SingleTransition, "none");
53 assert_parse!(SingleTransition, "opacity");
54 assert_parse!(SingleTransition, "opacity 1s");
55 assert_parse!(SingleTransition, "opacity 1s ease-in");
56 assert_parse!(SingleTransition, "opacity 1s ease-in 2s");
57 assert_parse!(SingleTransition, "2s ease-in");
58 assert_parse!(SingleTransition, "1s opacity", "opacity 1s");
59 assert_parse!(SingleTransition, "ease-in 1s opacity", "opacity 1s ease-in");
60 assert_parse!(SingleTransition, "1s 2s ease-in opacity", "opacity 1s ease-in 2s");
61 assert_parse!(SingleTransition, "ease-in opacity 1s 2s", "opacity 1s ease-in 2s");
62 assert_parse!(SingleTransition, "ease-in");
63 assert_parse!(SingleTransition, "1s");
64 assert_parse!(SingleTransition, "1s 2s");
65 assert_parse!(SingleTransition, "all 1s ease-in 2s");
66 assert_parse!(SingleTransition, "none 1s");
67 assert_parse!(SingleTransition, "none 1s normal");
68 assert_parse!(SingleTransition, "1s opacity allow-discrete", "opacity 1s allow-discrete");
69 }
70
71 #[test]
72 fn test_errors() {
73 assert_parse_error!(SingleTransition, "1deg");
74 assert_parse_error!(SingleTransition, "none none");
75 }
76
77 #[test]
78 fn test_visits() {
79 assert_visits!("1s", SingleTransition, Time);
80 assert_visits!("ease-in", SingleTransition, EasingFunction);
81 assert_visits!("1s 2s", SingleTransition, Time, Time);
82 assert_visits!("1s ease-in 2s", SingleTransition, Time, EasingFunction, Time);
83 }
84}