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}