1use alloc::string::{String, ToString};
11use crate::corety::AzString;
12
13use crate::props::formatter::PrintAsCssValue;
14
15#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
23#[repr(C)]
24#[derive(Default)]
28pub enum LayoutWritingMode {
29 #[default]
31 HorizontalTb,
32 VerticalRl,
34 VerticalLr,
37}
38
39
40impl LayoutWritingMode {
41 pub const fn is_vertical(self) -> bool {
43 matches!(self, Self::VerticalRl | Self::VerticalLr)
44 }
45}
46
47impl core::fmt::Debug for LayoutWritingMode {
48 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
49 write!(f, "{}", self.print_as_css_value())
50 }
51}
52
53impl core::fmt::Display for LayoutWritingMode {
54 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
55 write!(f, "{}", self.print_as_css_value())
56 }
57}
58
59impl PrintAsCssValue for LayoutWritingMode {
60 fn print_as_css_value(&self) -> String {
61 match self {
62 LayoutWritingMode::HorizontalTb => "horizontal-tb".to_string(),
63 LayoutWritingMode::VerticalRl => "vertical-rl".to_string(),
64 LayoutWritingMode::VerticalLr => "vertical-lr".to_string(),
65 }
66 }
67}
68
69#[cfg(feature = "parser")]
70#[derive(Clone, PartialEq)]
71pub enum LayoutWritingModeParseError<'a> {
72 InvalidValue(&'a str),
73}
74
75#[cfg(feature = "parser")]
76impl_debug_as_display!(LayoutWritingModeParseError<'a>);
77#[cfg(feature = "parser")]
78impl_display! { LayoutWritingModeParseError<'a>, {
79 InvalidValue(e) => format!("Invalid writing-mode value: \"{}\"", e),
80}}
81
82#[cfg(feature = "parser")]
83#[derive(Debug, Clone, PartialEq)]
84#[repr(C, u8)]
85pub enum LayoutWritingModeParseErrorOwned {
86 InvalidValue(AzString),
87}
88
89#[cfg(feature = "parser")]
90impl<'a> LayoutWritingModeParseError<'a> {
91 pub fn to_contained(&self) -> LayoutWritingModeParseErrorOwned {
92 match self {
93 LayoutWritingModeParseError::InvalidValue(s) => {
94 LayoutWritingModeParseErrorOwned::InvalidValue(s.to_string().into())
95 }
96 }
97 }
98}
99
100#[cfg(feature = "parser")]
101impl LayoutWritingModeParseErrorOwned {
102 pub fn to_shared<'a>(&'a self) -> LayoutWritingModeParseError<'a> {
103 match self {
104 LayoutWritingModeParseErrorOwned::InvalidValue(s) => {
105 LayoutWritingModeParseError::InvalidValue(s.as_str())
106 }
107 }
108 }
109}
110
111#[cfg(feature = "parser")]
112pub fn parse_layout_writing_mode<'a>(
113 input: &'a str,
114) -> Result<LayoutWritingMode, LayoutWritingModeParseError<'a>> {
115 let input = input.trim();
116 match input {
117 "horizontal-tb" => Ok(LayoutWritingMode::HorizontalTb),
118 "vertical-rl" => Ok(LayoutWritingMode::VerticalRl),
119 "vertical-lr" => Ok(LayoutWritingMode::VerticalLr),
120 "tb-lr" => Ok(LayoutWritingMode::VerticalLr), _ => Err(LayoutWritingModeParseError::InvalidValue(input)),
122 }
123}
124
125#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
129#[repr(C)]
130#[derive(Default)]
131pub enum LayoutClear {
132 #[default]
134 None,
135 Left,
137 Right,
139 Both,
141}
142
143
144impl core::fmt::Debug for LayoutClear {
145 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
146 write!(f, "{}", self.print_as_css_value())
147 }
148}
149
150impl core::fmt::Display for LayoutClear {
151 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
152 write!(f, "{}", self.print_as_css_value())
153 }
154}
155
156impl PrintAsCssValue for LayoutClear {
157 fn print_as_css_value(&self) -> String {
158 match self {
159 LayoutClear::None => "none".to_string(),
160 LayoutClear::Left => "left".to_string(),
161 LayoutClear::Right => "right".to_string(),
162 LayoutClear::Both => "both".to_string(),
163 }
164 }
165}
166
167#[cfg(feature = "parser")]
168#[derive(Clone, PartialEq)]
169pub enum LayoutClearParseError<'a> {
170 InvalidValue(&'a str),
171}
172
173#[cfg(feature = "parser")]
174impl_debug_as_display!(LayoutClearParseError<'a>);
175#[cfg(feature = "parser")]
176impl_display! { LayoutClearParseError<'a>, {
177 InvalidValue(e) => format!("Invalid clear value: \"{}\"", e),
178}}
179
180#[cfg(feature = "parser")]
181#[derive(Debug, Clone, PartialEq)]
182#[repr(C, u8)]
183pub enum LayoutClearParseErrorOwned {
184 InvalidValue(AzString),
185}
186
187#[cfg(feature = "parser")]
188impl<'a> LayoutClearParseError<'a> {
189 pub fn to_contained(&self) -> LayoutClearParseErrorOwned {
190 match self {
191 LayoutClearParseError::InvalidValue(s) => {
192 LayoutClearParseErrorOwned::InvalidValue(s.to_string().into())
193 }
194 }
195 }
196}
197
198#[cfg(feature = "parser")]
199impl LayoutClearParseErrorOwned {
200 pub fn to_shared<'a>(&'a self) -> LayoutClearParseError<'a> {
201 match self {
202 LayoutClearParseErrorOwned::InvalidValue(s) => {
203 LayoutClearParseError::InvalidValue(s.as_str())
204 }
205 }
206 }
207}
208
209#[cfg(feature = "parser")]
210pub fn parse_layout_clear<'a>(input: &'a str) -> Result<LayoutClear, LayoutClearParseError<'a>> {
211 let input = input.trim();
212 match input {
213 "none" => Ok(LayoutClear::None),
214 "left" => Ok(LayoutClear::Left),
215 "right" => Ok(LayoutClear::Right),
216 "both" => Ok(LayoutClear::Both),
217 _ => Err(LayoutClearParseError::InvalidValue(input)),
218 }
219}
220
221#[cfg(all(test, feature = "parser"))]
222mod tests {
223 use super::*;
224
225 #[test]
227 fn test_parse_writing_mode_horizontal_tb() {
228 assert_eq!(
229 parse_layout_writing_mode("horizontal-tb").unwrap(),
230 LayoutWritingMode::HorizontalTb
231 );
232 }
233
234 #[test]
235 fn test_parse_writing_mode_vertical_rl() {
236 assert_eq!(
237 parse_layout_writing_mode("vertical-rl").unwrap(),
238 LayoutWritingMode::VerticalRl
239 );
240 }
241
242 #[test]
243 fn test_parse_writing_mode_vertical_lr() {
244 assert_eq!(
245 parse_layout_writing_mode("vertical-lr").unwrap(),
246 LayoutWritingMode::VerticalLr
247 );
248 }
249
250 #[test]
251 fn test_parse_writing_mode_invalid() {
252 assert!(parse_layout_writing_mode("invalid").is_err());
253 assert!(parse_layout_writing_mode("horizontal").is_err());
254 }
255
256 #[test]
257 fn test_parse_writing_mode_whitespace() {
258 assert_eq!(
259 parse_layout_writing_mode(" vertical-rl ").unwrap(),
260 LayoutWritingMode::VerticalRl
261 );
262 }
263
264 #[test]
266 fn test_parse_layout_clear_none() {
267 assert_eq!(parse_layout_clear("none").unwrap(), LayoutClear::None);
268 }
269
270 #[test]
271 fn test_parse_layout_clear_left() {
272 assert_eq!(parse_layout_clear("left").unwrap(), LayoutClear::Left);
273 }
274
275 #[test]
276 fn test_parse_layout_clear_right() {
277 assert_eq!(parse_layout_clear("right").unwrap(), LayoutClear::Right);
278 }
279
280 #[test]
281 fn test_parse_layout_clear_both() {
282 assert_eq!(parse_layout_clear("both").unwrap(), LayoutClear::Both);
283 }
284
285 #[test]
286 fn test_parse_layout_clear_invalid() {
287 assert!(parse_layout_clear("invalid").is_err());
288 assert!(parse_layout_clear("all").is_err());
289 }
290
291 #[test]
292 fn test_parse_layout_clear_whitespace() {
293 assert_eq!(parse_layout_clear(" both ").unwrap(), LayoutClear::Both);
294 }
295
296 #[test]
298 fn test_print_writing_mode() {
299 assert_eq!(
300 LayoutWritingMode::HorizontalTb.print_as_css_value(),
301 "horizontal-tb"
302 );
303 assert_eq!(
304 LayoutWritingMode::VerticalRl.print_as_css_value(),
305 "vertical-rl"
306 );
307 assert_eq!(
308 LayoutWritingMode::VerticalLr.print_as_css_value(),
309 "vertical-lr"
310 );
311 }
312
313 #[test]
314 fn test_print_layout_clear() {
315 assert_eq!(LayoutClear::None.print_as_css_value(), "none");
316 assert_eq!(LayoutClear::Left.print_as_css_value(), "left");
317 assert_eq!(LayoutClear::Right.print_as_css_value(), "right");
318 assert_eq!(LayoutClear::Both.print_as_css_value(), "both");
319 }
320}