Skip to main content

azul_css/props/style/
lists.rs

1//! CSS list styling properties (`list-style-type` and `list-style-position`)
2
3use alloc::string::{String, ToString};
4use core::fmt;
5use crate::corety::AzString;
6
7use crate::{format_rust_code::FormatAsRustCode, props::formatter::PrintAsCssValue};
8
9// --- list-style-type ---
10
11/// CSS `list-style-type` property — controls the marker style for list items.
12#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[repr(C)]
14#[derive(Default)]
15pub enum StyleListStyleType {
16    None,
17    #[default]
18    Disc,
19    Circle,
20    Square,
21    Decimal,
22    DecimalLeadingZero,
23    LowerRoman,
24    UpperRoman,
25    LowerGreek,
26    UpperGreek,
27    LowerAlpha,
28    UpperAlpha,
29}
30
31
32impl PrintAsCssValue for StyleListStyleType {
33    fn print_as_css_value(&self) -> String {
34        use StyleListStyleType::*;
35        String::from(match self {
36            None => "none",
37            Disc => "disc",
38            Circle => "circle",
39            Square => "square",
40            Decimal => "decimal",
41            DecimalLeadingZero => "decimal-leading-zero",
42            LowerRoman => "lower-roman",
43            UpperRoman => "upper-roman",
44            LowerGreek => "lower-greek",
45            UpperGreek => "upper-greek",
46            LowerAlpha => "lower-alpha",
47            UpperAlpha => "upper-alpha",
48        })
49    }
50}
51
52impl FormatAsRustCode for StyleListStyleType {
53    fn format_as_rust_code(&self, _tabs: usize) -> String {
54        use StyleListStyleType::*;
55        format!(
56            "StyleListStyleType::{}",
57            match self {
58                None => "None",
59                Disc => "Disc",
60                Circle => "Circle",
61                Square => "Square",
62                Decimal => "Decimal",
63                DecimalLeadingZero => "DecimalLeadingZero",
64                LowerRoman => "LowerRoman",
65                UpperRoman => "UpperRoman",
66                LowerGreek => "LowerGreek",
67                UpperGreek => "UpperGreek",
68                LowerAlpha => "LowerAlpha",
69                UpperAlpha => "UpperAlpha",
70            }
71        )
72    }
73}
74
75impl fmt::Display for StyleListStyleType {
76    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77        write!(f, "{}", self.print_as_css_value())
78    }
79}
80
81// --- list-style-position ---
82
83/// CSS `list-style-position` property — controls whether the marker is inside or outside the list item box.
84#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
85#[repr(C)]
86#[derive(Default)]
87pub enum StyleListStylePosition {
88    Inside,
89    #[default]
90    Outside,
91}
92
93
94impl PrintAsCssValue for StyleListStylePosition {
95    fn print_as_css_value(&self) -> String {
96        use StyleListStylePosition::*;
97        String::from(match self {
98            Inside => "inside",
99            Outside => "outside",
100        })
101    }
102}
103
104impl FormatAsRustCode for StyleListStylePosition {
105    fn format_as_rust_code(&self, _tabs: usize) -> String {
106        use StyleListStylePosition::*;
107        format!(
108            "StyleListStylePosition::{}",
109            match self {
110                Inside => "Inside",
111                Outside => "Outside",
112            }
113        )
114    }
115}
116
117impl fmt::Display for StyleListStylePosition {
118    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119        write!(f, "{}", self.print_as_css_value())
120    }
121}
122
123// --- Parsing Logic ---
124
125#[cfg(feature = "parser")]
126#[derive(Clone, PartialEq)]
127pub enum StyleListStyleTypeParseError<'a> {
128    InvalidValue(&'a str),
129}
130
131#[cfg(feature = "parser")]
132impl_debug_as_display!(StyleListStyleTypeParseError<'a>);
133
134#[cfg(feature = "parser")]
135impl_display! { StyleListStyleTypeParseError<'a>, {
136    InvalidValue(val) => format!("Invalid list-style-type value: \"{}\"", val),
137}}
138
139#[cfg(feature = "parser")]
140#[derive(Debug, Clone, PartialEq)]
141#[repr(C, u8)]
142pub enum StyleListStyleTypeParseErrorOwned {
143    InvalidValue(AzString),
144}
145
146#[cfg(feature = "parser")]
147impl<'a> StyleListStyleTypeParseError<'a> {
148    pub fn to_contained(&self) -> StyleListStyleTypeParseErrorOwned {
149        match self {
150            Self::InvalidValue(s) => StyleListStyleTypeParseErrorOwned::InvalidValue(s.to_string().into()),
151        }
152    }
153}
154
155#[cfg(feature = "parser")]
156impl StyleListStyleTypeParseErrorOwned {
157    pub fn to_shared<'a>(&'a self) -> StyleListStyleTypeParseError<'a> {
158        match self {
159            Self::InvalidValue(s) => StyleListStyleTypeParseError::InvalidValue(s.as_str()),
160        }
161    }
162}
163
164/// Parses a CSS `list-style-type` value from a string.
165#[cfg(feature = "parser")]
166pub fn parse_style_list_style_type<'a>(
167    input: &'a str,
168) -> Result<StyleListStyleType, StyleListStyleTypeParseError<'a>> {
169    let input = input.trim();
170    match input {
171        "none" => Ok(StyleListStyleType::None),
172        "disc" => Ok(StyleListStyleType::Disc),
173        "circle" => Ok(StyleListStyleType::Circle),
174        "square" => Ok(StyleListStyleType::Square),
175        "decimal" => Ok(StyleListStyleType::Decimal),
176        "decimal-leading-zero" => Ok(StyleListStyleType::DecimalLeadingZero),
177        "lower-roman" => Ok(StyleListStyleType::LowerRoman),
178        "upper-roman" => Ok(StyleListStyleType::UpperRoman),
179        "lower-greek" => Ok(StyleListStyleType::LowerGreek),
180        "upper-greek" => Ok(StyleListStyleType::UpperGreek),
181        "lower-alpha" | "lower-latin" => Ok(StyleListStyleType::LowerAlpha),
182        "upper-alpha" | "upper-latin" => Ok(StyleListStyleType::UpperAlpha),
183        _ => Err(StyleListStyleTypeParseError::InvalidValue(input)),
184    }
185}
186
187#[cfg(feature = "parser")]
188#[derive(Clone, PartialEq)]
189pub enum StyleListStylePositionParseError<'a> {
190    InvalidValue(&'a str),
191}
192
193#[cfg(feature = "parser")]
194impl_debug_as_display!(StyleListStylePositionParseError<'a>);
195
196#[cfg(feature = "parser")]
197impl_display! { StyleListStylePositionParseError<'a>, {
198    InvalidValue(val) => format!("Invalid list-style-position value: \"{}\"", val),
199}}
200
201#[cfg(feature = "parser")]
202#[derive(Debug, Clone, PartialEq)]
203#[repr(C, u8)]
204pub enum StyleListStylePositionParseErrorOwned {
205    InvalidValue(AzString),
206}
207
208#[cfg(feature = "parser")]
209impl<'a> StyleListStylePositionParseError<'a> {
210    pub fn to_contained(&self) -> StyleListStylePositionParseErrorOwned {
211        match self {
212            Self::InvalidValue(s) => {
213                StyleListStylePositionParseErrorOwned::InvalidValue(s.to_string().into())
214            }
215        }
216    }
217}
218
219#[cfg(feature = "parser")]
220impl StyleListStylePositionParseErrorOwned {
221    pub fn to_shared<'a>(&'a self) -> StyleListStylePositionParseError<'a> {
222        match self {
223            Self::InvalidValue(s) => StyleListStylePositionParseError::InvalidValue(s.as_str()),
224        }
225    }
226}
227
228/// Parses a CSS `list-style-position` value from a string.
229#[cfg(feature = "parser")]
230pub fn parse_style_list_style_position<'a>(
231    input: &'a str,
232) -> Result<StyleListStylePosition, StyleListStylePositionParseError<'a>> {
233    let input = input.trim();
234    match input {
235        "inside" => Ok(StyleListStylePosition::Inside),
236        "outside" => Ok(StyleListStylePosition::Outside),
237        _ => Err(StyleListStylePositionParseError::InvalidValue(input)),
238    }
239}