1use super::prelude::*;
2
3#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
6#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
7#[cfg_attr(feature = "css_feature_data", derive(::csskit_derives::ToCSSFeature), css_feature("css.at-rules.layer"))]
8#[derive(csskit_derives::NodeWithMetadata)]
9#[metadata(node_kinds = AtRule, used_at_rules = Layer)]
10pub struct LayerRule<'a> {
11 #[cfg_attr(feature = "visitable", visit(skip))]
12 #[atom(CssAtomSet::Layer)]
13 pub name: T![AtKeyword],
14 pub prelude: LayerNameList<'a>,
15 #[metadata(delegate)]
16 pub block: Option<LayerRuleBlock<'a>>,
17 #[cfg_attr(feature = "visitable", visit(skip))]
18 pub semicolon: Option<T![;]>,
19}
20
21#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable))]
23#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
24pub struct LayerNameList<'a>(pub CommaSeparated<'a, LayerName<'a>>);
25
26#[derive(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(self))]
29#[derive(csskit_derives::NodeWithMetadata)]
30pub struct LayerName<'a>(T![Ident], Vec<'a, (T![.], T![Ident])>);
31
32impl<'a> Parse<'a> for LayerName<'a> {
33 fn parse<I>(p: &mut Parser<'a, I>) -> ParserResult<Self>
34 where
35 I: Iterator<Item = Cursor> + Clone,
36 {
37 let mut parts = Vec::new_in(p.bump());
38 let first = p.parse::<T![Ident]>()?;
39 loop {
40 if p.peek::<T![.]>() {
41 let dot = p.parse::<T![.]>()?;
42 let ident = p.parse::<T![Ident]>()?;
43 parts.push((dot, ident));
44 } else {
45 return Ok(Self(first, parts));
46 }
47 }
48 }
49}
50
51#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
52#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable))]
53#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
54#[derive(csskit_derives::NodeWithMetadata)]
55pub struct LayerRuleBlock<'a>(#[metadata(delegate)] pub RuleList<'a, Rule<'a>, CssMetadata>);
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use crate::CssAtomSet;
61 use css_parse::assert_parse;
62
63 #[test]
64 fn size_test() {
65 assert_eq!(std::mem::size_of::<LayerRule>(), 160);
66 assert_eq!(std::mem::size_of::<LayerNameList>(), 32);
67 assert_eq!(std::mem::size_of::<LayerName>(), 48);
68 assert_eq!(std::mem::size_of::<LayerRuleBlock>(), 96);
69 }
70
71 #[test]
72 fn test_writes() {
73 assert_parse!(CssAtomSet::ATOMS, LayerRule, "@layer foo{}");
74 assert_parse!(CssAtomSet::ATOMS, LayerRule, "@layer foo;");
75 assert_parse!(CssAtomSet::ATOMS, LayerRule, "@layer foo,bar;");
76 assert_parse!(CssAtomSet::ATOMS, LayerRule, "@layer foo.bar,baz.bing.baz;");
77 assert_parse!(CssAtomSet::ATOMS, LayerRule, "@layer foo.bar{body{color:black}}");
78 }
79}