1use crate::units::CSSInt;
2use css_parse::{Parse, Parser, Result as ParserResult, T};
3use csskit_derives::{Peek, ToCursors, ToSpan, Visitable};
4
5#[derive(Peek, ToCursors, ToSpan, Visitable, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
8#[visit(self)]
9pub struct Ratio {
10 pub numerator: CSSInt,
11 pub slash: Option<T![/]>,
12 pub denominator: Option<CSSInt>,
13}
14
15impl<'a> Parse<'a> for Ratio {
16 fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
17 let numerator = p.parse::<CSSInt>()?;
18 let slash = p.parse_if_peek::<T![/]>()?;
19 let denominator = if slash.is_some() { Some(p.parse::<CSSInt>()?) } else { None };
20 Ok(Self { numerator, slash, denominator })
21 }
22}
23
24#[cfg(test)]
25mod tests {
26 use super::*;
27 use css_parse::{assert_parse, assert_parse_error};
28
29 #[test]
30 fn size_test() {
31 assert_eq!(std::mem::size_of::<Ratio>(), 44);
32 }
33
34 #[test]
35 fn test_writes() {
36 assert_parse!(Ratio, "1/1");
37 assert_parse!(Ratio, "5/3");
38 assert_parse!(Ratio, "5");
39 }
40
41 #[test]
42 fn test_errors() {
43 assert_parse_error!(Ratio, "5 : 3");
44 assert_parse_error!(Ratio, "5 / 1 / 1");
45 }
46
47 }