css_ast/selector/
combinator.rs1use css_parse::{Parse, Parser, Result as ParserResult, T};
2use csskit_derives::{ToCursors, ToSpan, Visitable};
3
4#[derive(ToSpan, ToCursors, Visitable, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(rename_all = "kebab-case"))]
7#[visit(self)]
8pub enum Combinator {
9 Child(T![>]),
10 NextSibling(T![+]),
11 SubsequentSibling(T![~]),
12 Column(T![||]),
13 Nesting(T![&]),
14 Descendant(T![' ']),
15}
16
17impl<'a> Parse<'a> for Combinator {
18 fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
19 if p.peek::<T![>]>() {
20 Ok(Self::Child(p.parse::<T![>]>()?))
21 } else if p.peek::<T![+]>() {
22 Ok(Self::NextSibling(p.parse::<T![+]>()?))
23 } else if p.peek::<T![~]>() {
24 Ok(Self::SubsequentSibling(p.parse::<T![~]>()?))
25 } else if p.peek::<T![&]>() {
26 Ok(Self::Nesting(p.parse::<T![&]>()?))
27 } else if p.peek::<T![||]>() {
28 Ok(Self::Column(p.parse::<T![||]>()?))
29 } else {
30 Ok(Self::Descendant(p.parse::<T![' ']>()?))
31 }
32 }
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38 use css_parse::assert_parse;
39
40 #[test]
41 fn size_test() {
42 assert_eq!(std::mem::size_of::<Combinator>(), 28);
43 }
44
45 #[test]
46 fn test_writes() {
47 assert_parse!(Combinator, ">");
48 assert_parse!(Combinator, "+");
49 assert_parse!(Combinator, "~");
50 assert_parse!(Combinator, "&");
51 assert_parse!(Combinator, " ");
53 assert_parse!(Combinator, " ");
54 assert_parse!(Combinator, " /**/ /**/ /**/ ", " ");
55 assert_parse!(Combinator, "||");
57 }
58}