Skip to main content

takumi_css/style/properties/grid/
grid_length.rs

1use cssparser::{Parser, Token};
2use taffy::CompactLength;
3
4use crate::style::{
5  CssToken, FromCss, Length, MakeComputed, ParseResult, SizingContext, ToCss, unexpected_token,
6};
7
8/// Represents a grid track sizing function with serde support
9#[derive(Debug, Clone, Copy, PartialEq)]
10#[non_exhaustive]
11pub enum GridLength {
12  /// A fraction of the available space
13  Fr(f32),
14  /// A fixed length
15  Unit(Length),
16}
17
18impl GridLength {
19  /// Converts the grid track size to a compact length representation.
20  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
28// Minimal CSS parsing helpers for grid values (mirror patterns used in other property modules)
29impl<'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}