takumi_css/style/properties/grid/
grid_repetition_count.rs1use crate::style::unexpected_token;
2use cssparser::{Parser, Token};
3
4use crate::style::{CssSyntaxKind, CssToken, FromCss, ParseResult, ToCss};
5
6#[derive(Debug, Clone, Copy, PartialEq)]
8#[non_exhaustive]
9pub enum GridRepetitionKeyword {
10 AutoFill,
12 AutoFit,
14}
15
16#[derive(Debug, Clone, Copy, PartialEq)]
18#[non_exhaustive]
19pub enum GridRepetitionCount {
20 Keyword(GridRepetitionKeyword),
22 Count(u16),
24}
25
26impl From<GridRepetitionCount> for taffy::RepetitionCount {
27 fn from(repetition: GridRepetitionCount) -> Self {
28 match repetition {
29 GridRepetitionCount::Keyword(GridRepetitionKeyword::AutoFill) => {
30 taffy::RepetitionCount::AutoFill
31 }
32 GridRepetitionCount::Keyword(GridRepetitionKeyword::AutoFit) => {
33 taffy::RepetitionCount::AutoFit
34 }
35 GridRepetitionCount::Count(count) => taffy::RepetitionCount::Count(count),
36 }
37 }
38}
39
40impl<'i> FromCss<'i> for GridRepetitionCount {
41 fn from_css(input: &mut Parser<'i, '_>) -> ParseResult<'i, Self> {
42 let location = input.current_source_location();
43 if let Ok(ident) = input.try_parse(Parser::expect_ident_cloned) {
44 let ident_str = ident.as_ref();
45 if ident_str.eq_ignore_ascii_case("auto-fill") {
46 return Ok(GridRepetitionCount::Keyword(
47 GridRepetitionKeyword::AutoFill,
48 ));
49 }
50 if ident_str.eq_ignore_ascii_case("auto-fit") {
51 return Ok(GridRepetitionCount::Keyword(GridRepetitionKeyword::AutoFit));
52 }
53 return Err(unexpected_token!(location, &Token::Ident(ident)));
54 }
55
56 let token = input.next()?;
57 match *token {
58 Token::Number {
59 int_value, value, ..
60 } => {
61 let count: i64 = if let Some(iv) = int_value {
63 iv as i64
64 } else {
65 value as i64
66 };
67 if count < 0 {
68 return Err::<Self, _>(
69 location
70 .new_basic_unexpected_token_error(token.clone())
71 .into(),
72 );
73 }
74 Ok(GridRepetitionCount::Count(count as u16))
75 }
76 _ => Err(unexpected_token!(location, token)),
77 }
78 }
79
80 const VALID_TOKENS: &'static [CssToken] = &[
81 CssToken::Keyword("auto-fill"),
82 CssToken::Keyword("auto-fit"),
83 CssToken::Syntax(CssSyntaxKind::Number),
84 ];
85}
86
87impl ToCss for GridRepetitionKeyword {
88 fn to_css<W: std::fmt::Write>(&self, dest: &mut W) -> std::fmt::Result {
89 match self {
90 Self::AutoFill => dest.write_str("auto-fill"),
91 Self::AutoFit => dest.write_str("auto-fit"),
92 }
93 }
94}
95
96impl ToCss for GridRepetitionCount {
97 fn to_css<W: std::fmt::Write>(&self, dest: &mut W) -> std::fmt::Result {
98 match self {
99 Self::Keyword(kw) => kw.to_css(dest),
100 Self::Count(c) => write!(dest, "{}", c),
101 }
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn test_parse_repetition_count() {
111 assert_eq!(
112 GridRepetitionCount::from_str("auto-fill"),
113 Ok(GridRepetitionCount::Keyword(
114 GridRepetitionKeyword::AutoFill
115 ))
116 );
117
118 assert_eq!(
119 GridRepetitionCount::from_str("auto-fit"),
120 Ok(GridRepetitionCount::Keyword(GridRepetitionKeyword::AutoFit))
121 );
122
123 assert_eq!(
124 GridRepetitionCount::from_str("3"),
125 Ok(GridRepetitionCount::Count(3))
126 );
127 }
128}