css_ast/units/
number.rs

1use css_parse::{Build, Cursor, Parser, Peek, T, keyword_set};
2use csskit_derives::{IntoCursor, Peek, ToCursors};
3
4keyword_set!(enum InfinityKeyword {
5	Infnity: "infinity",
6	NegInfnity: "-infinity",
7});
8
9#[derive(ToCursors, IntoCursor, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(rename_all = "kebab-case"))]
11pub enum NumberOrInfinity {
12	Number(T![Number]),
13	Infinity(T![Ident]),
14	NegInfinity(T![Ident]),
15}
16
17impl<'a> Peek<'a> for NumberOrInfinity {
18	fn peek(p: &Parser<'a>, c: Cursor) -> bool {
19		<T![Number]>::peek(p, c) || InfinityKeyword::peek(p, c)
20	}
21}
22
23impl<'a> Build<'a> for NumberOrInfinity {
24	fn build(p: &Parser<'a>, c: Cursor) -> Self {
25		debug_assert!(Self::peek(p, c));
26		if <T![Number]>::peek(p, c) {
27			Self::Number(<T![Number]>::build(p, c))
28		} else {
29			match InfinityKeyword::build(p, c) {
30				InfinityKeyword::Infnity(t) => Self::Infinity(t),
31				InfinityKeyword::NegInfnity(t) => Self::NegInfinity(t),
32			}
33		}
34	}
35}
36
37#[derive(Peek, ToCursors, IntoCursor, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
38#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(rename_all = "kebab-case"))]
39pub enum NumberOrPercentage {
40	Number(T![Number]),
41	Percentage(T![Dimension::%]),
42}
43
44impl<'a> Build<'a> for NumberOrPercentage {
45	fn build(p: &Parser<'a>, c: Cursor) -> Self {
46		debug_assert!(Self::peek(p, c));
47		if <T![Number]>::peek(p, c) {
48			Self::Number(<T![Number]>::build(p, c))
49		} else {
50			Self::Percentage(<T![Dimension::%]>::build(p, c))
51		}
52	}
53}
54
55impl From<NumberOrPercentage> for f32 {
56	fn from(val: NumberOrPercentage) -> Self {
57		match val {
58			NumberOrPercentage::Number(f) => f.into(),
59			NumberOrPercentage::Percentage(f) => f.into(),
60		}
61	}
62}
63
64#[cfg(test)]
65mod tests {
66	use super::*;
67	use css_parse::assert_parse;
68
69	#[test]
70	fn size_test() {
71		assert_eq!(std::mem::size_of::<NumberOrInfinity>(), 16);
72	}
73
74	#[test]
75	fn test_writes() {
76		assert_parse!(NumberOrInfinity, "10000000");
77		assert_parse!(NumberOrInfinity, "infinity");
78		assert_parse!(NumberOrInfinity, "-infinity");
79	}
80}