css_parse/
comparison.rs

1use crate::{Diagnostic, Parse, Parser, Peek, Result, SemanticEq, T, ToCursors};
2
3/// This enum represents a set of comparison operators, used in Ranged Media Features (see
4/// [RangedFeature][crate::RangedFeature]), and could be used in other parts of a CSS-alike language. This isn't a
5/// strictly standard part of CSS, but is provided for convenience.
6///
7/// [Comparison] is defined as:
8///
9/// ```md
10/// <comparison>
11///  │├──╮─ "="  ─╭──┤│
12///      ├─ "<"  ─┤
13///      ├─ "<=" ─┤
14///      ├─ ">"  ─┤
15///      ╰─ ">=" ─╯
16/// ```
17///
18#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
20pub enum Comparison {
21	LessThan(T![<]),
22	GreaterThan(T![>]),
23	GreaterThanEqual(T![>=]),
24	LessThanEqual(T![<=]),
25	Equal(T![=]),
26}
27
28impl<'a> Parse<'a> for Comparison {
29	fn parse<I>(p: &mut Parser<'a, I>) -> Result<Comparison>
30	where
31		I: Iterator<Item = crate::Cursor> + Clone,
32	{
33		let c = p.peek_n(1);
34		match c.token().char() {
35			Some('=') => p.parse::<T![=]>().map(Comparison::Equal),
36			Some('>') => {
37				if <T![>=]>::peek(p, c) {
38					p.parse::<T![>=]>().map(Comparison::GreaterThanEqual)
39				} else {
40					p.parse::<T![>]>().map(Comparison::GreaterThan)
41				}
42			}
43			Some('<') => {
44				if <T![<=]>::peek(p, c) {
45					p.parse::<T![<=]>().map(Comparison::LessThanEqual)
46				} else {
47					p.parse::<T![<]>().map(Comparison::LessThan)
48				}
49			}
50			Some(_) => Err(Diagnostic::new(p.next(), Diagnostic::unexpected_delim))?,
51			_ => Err(Diagnostic::new(p.next(), Diagnostic::unexpected))?,
52		}
53	}
54}
55
56impl ToCursors for Comparison {
57	fn to_cursors(&self, s: &mut impl crate::CursorSink) {
58		match self {
59			Self::LessThan(c) => ToCursors::to_cursors(c, s),
60			Self::GreaterThan(c) => ToCursors::to_cursors(c, s),
61			Self::GreaterThanEqual(c) => ToCursors::to_cursors(c, s),
62			Self::LessThanEqual(c) => ToCursors::to_cursors(c, s),
63			Self::Equal(c) => ToCursors::to_cursors(c, s),
64		}
65	}
66}
67
68impl SemanticEq for Comparison {
69	fn semantic_eq(&self, other: &Self) -> bool {
70		match (self, other) {
71			(Self::LessThan(a), Self::LessThan(b)) => a.semantic_eq(b),
72			(Self::GreaterThan(a), Self::GreaterThan(b)) => a.semantic_eq(b),
73			(Self::GreaterThanEqual(a), Self::GreaterThanEqual(b)) => a.semantic_eq(b),
74			(Self::LessThanEqual(a), Self::LessThanEqual(b)) => a.semantic_eq(b),
75			(Self::Equal(a), Self::Equal(b)) => a.semantic_eq(b),
76			_ => false,
77		}
78	}
79}