takumi_css/style/properties/grid/
grid_length.rs1use cssparser::{Parser, Token};
2use taffy::CompactLength;
3
4use crate::style::{
5 CssToken, FromCss, Length, MakeComputed, ParseResult, SizingContext, ToCss, unexpected_token,
6};
7
8#[derive(Debug, Clone, Copy, PartialEq)]
10#[non_exhaustive]
11pub enum GridLength {
12 Fr(f32),
14 Unit(Length),
16}
17
18impl GridLength {
19 pub fn to_compact_length(self, sizing: &SizingContext) -> CompactLength {
21 match self {
22 GridLength::Fr(fr) => CompactLength::fr(fr),
23 GridLength::Unit(unit) => unit.to_compact_length(sizing),
24 }
25 }
26}
27
28impl<'i> FromCss<'i> for GridLength {
30 fn from_css(input: &mut Parser<'i, '_>) -> ParseResult<'i, Self> {
31 if let Ok(unit) = input.try_parse(Length::from_css) {
32 return Ok(GridLength::Unit(unit));
33 }
34
35 let location = input.current_source_location();
36 let token = input.next()?;
37
38 let Token::Dimension { value, unit, .. } = &token else {
39 return Err(unexpected_token!(location, token));
40 };
41
42 if !unit.eq_ignore_ascii_case("fr") {
43 return Err(unexpected_token!(location, token));
44 }
45
46 Ok(GridLength::Fr(*value))
47 }
48
49 const VALID_TOKENS: &'static [CssToken] = Length::<true>::VALID_TOKENS;
50}
51
52impl MakeComputed for GridLength {
53 fn make_computed(&mut self, sizing: &SizingContext) {
54 if let GridLength::Unit(unit) = self {
55 unit.make_computed(sizing);
56 }
57 }
58}
59
60impl ToCss for GridLength {
61 fn to_css<W: std::fmt::Write>(&self, dest: &mut W) -> std::fmt::Result {
62 match self {
63 Self::Fr(fr) => write!(dest, "{}fr", fr),
64 Self::Unit(u) => u.to_css(dest),
65 }
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_parse_fr_and_unit() {
75 assert_eq!(GridLength::from_str("1fr"), Ok(GridLength::Fr(1.0)));
76
77 assert_eq!(
78 GridLength::from_str("10px"),
79 Ok(GridLength::Unit(Length::Px(10.0)))
80 );
81 }
82}