1use bumpalo::collections::Vec;
2use css_parse::{AtRule, Parse, Parser, Result as ParserResult, RuleList, T, atkeyword_set, syntax::CommaSeparated};
3use csskit_derives::{Parse, Peek, ToCursors, ToSpan, Visitable};
4
5use crate::stylesheet::Rule;
6
7atkeyword_set!(pub struct AtLayerKeyword "layer");
8
9#[derive(Parse, Peek, ToCursors, ToSpan, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
12#[cfg_attr(feature = "css_feature_data", derive(::csskit_derives::ToCSSFeature), css_feature("css.at-rules.layer"))]
13#[visit]
14pub struct LayerRule<'a>(pub AtRule<AtLayerKeyword, LayerNameList<'a>, Option<LayerRuleBlock<'a>>>);
15
16#[derive(Parse, Peek, ToCursors, ToSpan, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
18pub struct LayerNameList<'a>(pub CommaSeparated<'a, LayerName<'a>>);
19
20#[derive(Peek, ToCursors, ToSpan, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
22#[visit(self)]
23pub struct LayerName<'a>(T![Ident], Vec<'a, (T![.], T![Ident])>);
24
25impl<'a> Parse<'a> for LayerName<'a> {
26 fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
27 let mut parts = Vec::new_in(p.bump());
28 let first = p.parse::<T![Ident]>()?;
29 loop {
30 if p.peek::<T![.]>() {
31 let dot = p.parse::<T![.]>()?;
32 let ident = p.parse::<T![Ident]>()?;
33 parts.push((dot, ident));
34 } else {
35 return Ok(Self(first, parts));
36 }
37 }
38 }
39}
40
41#[derive(Parse, Peek, ToCursors, ToSpan, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
43pub struct LayerRuleBlock<'a>(RuleList<'a, Rule<'a>>);
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use css_parse::assert_parse;
49
50 #[test]
51 fn size_test() {
52 assert_eq!(std::mem::size_of::<LayerRule>(), 128);
53 assert_eq!(std::mem::size_of::<LayerNameList>(), 32);
54 assert_eq!(std::mem::size_of::<LayerName>(), 48);
55 assert_eq!(std::mem::size_of::<LayerRuleBlock>(), 64);
56 }
57
58 #[test]
59 fn test_writes() {
60 assert_parse!(LayerRule, "@layer foo{}");
61 assert_parse!(LayerRule, "@layer foo;");
62 assert_parse!(LayerRule, "@layer foo,bar;");
63 assert_parse!(LayerRule, "@layer foo.bar,baz.bing.baz;");
64 assert_parse!(LayerRule, "@layer foo.bar{body{color:black}}");
65 }
66}