css_parse/macros/
pseudo_class.rs1#[macro_export]
38macro_rules! pseudo_class {
39 ($(#[$meta:meta])* $vis:vis enum $name: ident { $( $variant: ident: $variant_str: tt$(,)?)+ }) => {
40 $(#[$meta])*
41 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42 #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
43 pub enum $name {
44 $($variant($crate::T![:], $crate::T![Ident]),)+
45 }
46
47 impl<'a> $crate::Peek<'a> for $name {
48 fn peek(p: &$crate::Parser<'a>, c: $crate::Cursor) -> bool {
49 let c2 = p.peek_n(2);
50 c == $crate::Kind::Colon && (c2 == $crate::Kind::Ident && Self::MAP.get(&p.parse_str_lower(c2)).is_some())
51 }
52 }
53
54 impl<'a> $crate::Parse<'a> for $name {
55 fn parse(p: &mut $crate::Parser<'a>) -> $crate::Result<Self> {
56 let colon = p.parse::<$crate::T![:]>()?;
57 let skip = p.set_skip($crate::KindSet::NONE);
58 let ident = p.parse::<$crate::T![Ident]>();
59 p.set_skip(skip);
60 let ident = ident?;
61 if let Some(val) = Self::MAP.get(&p.parse_str_lower(ident.into())) {
62 match val {
63 $(Self::$variant(_, _) => Ok(Self::$variant(colon, ident)),)+
64 }
65 } else {
66 use $crate::ToSpan;
67 Err($crate::diagnostics::UnexpectedIdent(p.parse_str(ident.into()).into(), ident.into()))?
68 }
69 }
70 }
71
72 impl $crate::ToCursors for $name {
73 fn to_cursors(&self, s: &mut impl $crate::CursorSink) {
74 match self {
75 $(Self::$variant(colon, ident) => {
76 s.append((*colon).into());
77 s.append((*ident).into());
78 })+
79 }
80 }
81 }
82
83 impl $crate::ToSpan for $name {
84 fn to_span(&self) -> $crate::Span {
85 match self {
86 $($name::$variant(a, b) => a.to_span() + b.to_span(),)+
87 }
88 }
89 }
90
91 impl $name {
92 const MAP: phf::Map<&'static str, $name> = phf::phf_map! {
93 $($variant_str => $name::$variant(<$crate::T![:]>::dummy(), <$crate::T![Ident]>::dummy()),)+
94 };
95 }
96 }
97}