1use alloc::string::{String, ToString};
4
5use crate::props::formatter::PrintAsCssValue;
6
7#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[repr(C)]
12pub enum LayoutWrap {
13 NoWrap,
14 Wrap,
15 WrapReverse,
16}
17
18impl Default for LayoutWrap {
19 fn default() -> Self {
20 LayoutWrap::NoWrap
21 }
22}
23
24impl core::fmt::Debug for LayoutWrap {
25 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
26 write!(f, "{}", self.print_as_css_value())
27 }
28}
29
30impl core::fmt::Display for LayoutWrap {
31 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
32 write!(f, "{}", self.print_as_css_value())
33 }
34}
35
36impl PrintAsCssValue for LayoutWrap {
37 fn print_as_css_value(&self) -> String {
38 match self {
39 LayoutWrap::NoWrap => "nowrap".to_string(),
40 LayoutWrap::Wrap => "wrap".to_string(),
41 LayoutWrap::WrapReverse => "wrap-reverse".to_string(),
42 }
43 }
44}
45
46#[cfg(feature = "parser")]
47#[derive(Clone, PartialEq)]
48pub enum LayoutWrapParseError<'a> {
49 InvalidValue(&'a str),
50}
51
52#[cfg(feature = "parser")]
53impl_debug_as_display!(LayoutWrapParseError<'a>);
54#[cfg(feature = "parser")]
55impl_display! { LayoutWrapParseError<'a>, {
56 InvalidValue(e) => format!("Invalid flex-wrap value: \"{}\"", e),
57}}
58
59#[cfg(feature = "parser")]
60#[derive(Debug, Clone, PartialEq)]
61pub enum LayoutWrapParseErrorOwned {
62 InvalidValue(String),
63}
64
65#[cfg(feature = "parser")]
66impl<'a> LayoutWrapParseError<'a> {
67 pub fn to_contained(&self) -> LayoutWrapParseErrorOwned {
68 match self {
69 LayoutWrapParseError::InvalidValue(s) => {
70 LayoutWrapParseErrorOwned::InvalidValue(s.to_string())
71 }
72 }
73 }
74}
75
76#[cfg(feature = "parser")]
77impl LayoutWrapParseErrorOwned {
78 pub fn to_shared<'a>(&'a self) -> LayoutWrapParseError<'a> {
79 match self {
80 LayoutWrapParseErrorOwned::InvalidValue(s) => {
81 LayoutWrapParseError::InvalidValue(s.as_str())
82 }
83 }
84 }
85}
86
87#[cfg(feature = "parser")]
88pub fn parse_layout_wrap<'a>(input: &'a str) -> Result<LayoutWrap, LayoutWrapParseError<'a>> {
89 let input = input.trim();
90 match input {
91 "nowrap" => Ok(LayoutWrap::NoWrap),
92 "wrap" => Ok(LayoutWrap::Wrap),
93 "wrap-reverse" => Ok(LayoutWrap::WrapReverse),
94 _ => Err(LayoutWrapParseError::InvalidValue(input)),
95 }
96}
97
98#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
102#[repr(C)]
103pub enum LayoutWritingMode {
104 HorizontalTb,
105 VerticalRl,
106 VerticalLr,
107}
108
109impl Default for LayoutWritingMode {
110 fn default() -> Self {
111 LayoutWritingMode::HorizontalTb
112 }
113}
114
115impl LayoutWritingMode {
116 pub const fn is_vertical(self) -> bool {
118 matches!(self, Self::VerticalRl | Self::VerticalLr)
119 }
120}
121
122impl core::fmt::Debug for LayoutWritingMode {
123 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
124 write!(f, "{}", self.print_as_css_value())
125 }
126}
127
128impl core::fmt::Display for LayoutWritingMode {
129 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
130 write!(f, "{}", self.print_as_css_value())
131 }
132}
133
134impl PrintAsCssValue for LayoutWritingMode {
135 fn print_as_css_value(&self) -> String {
136 match self {
137 LayoutWritingMode::HorizontalTb => "horizontal-tb".to_string(),
138 LayoutWritingMode::VerticalRl => "vertical-rl".to_string(),
139 LayoutWritingMode::VerticalLr => "vertical-lr".to_string(),
140 }
141 }
142}
143
144#[cfg(feature = "parser")]
145#[derive(Clone, PartialEq)]
146pub enum LayoutWritingModeParseError<'a> {
147 InvalidValue(&'a str),
148}
149
150#[cfg(feature = "parser")]
151impl_debug_as_display!(LayoutWritingModeParseError<'a>);
152#[cfg(feature = "parser")]
153impl_display! { LayoutWritingModeParseError<'a>, {
154 InvalidValue(e) => format!("Invalid writing-mode value: \"{}\"", e),
155}}
156
157#[cfg(feature = "parser")]
158#[derive(Debug, Clone, PartialEq)]
159pub enum LayoutWritingModeParseErrorOwned {
160 InvalidValue(String),
161}
162
163#[cfg(feature = "parser")]
164impl<'a> LayoutWritingModeParseError<'a> {
165 pub fn to_contained(&self) -> LayoutWritingModeParseErrorOwned {
166 match self {
167 LayoutWritingModeParseError::InvalidValue(s) => {
168 LayoutWritingModeParseErrorOwned::InvalidValue(s.to_string())
169 }
170 }
171 }
172}
173
174#[cfg(feature = "parser")]
175impl LayoutWritingModeParseErrorOwned {
176 pub fn to_shared<'a>(&'a self) -> LayoutWritingModeParseError<'a> {
177 match self {
178 LayoutWritingModeParseErrorOwned::InvalidValue(s) => {
179 LayoutWritingModeParseError::InvalidValue(s.as_str())
180 }
181 }
182 }
183}
184
185#[cfg(feature = "parser")]
186pub fn parse_layout_writing_mode<'a>(
187 input: &'a str,
188) -> Result<LayoutWritingMode, LayoutWritingModeParseError<'a>> {
189 let input = input.trim();
190 match input {
191 "horizontal-tb" => Ok(LayoutWritingMode::HorizontalTb),
192 "vertical-rl" => Ok(LayoutWritingMode::VerticalRl),
193 "vertical-lr" => Ok(LayoutWritingMode::VerticalLr),
194 _ => Err(LayoutWritingModeParseError::InvalidValue(input)),
195 }
196}
197
198#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
202#[repr(C)]
203pub enum LayoutClear {
204 None,
205 Left,
206 Right,
207 Both,
208}
209
210impl Default for LayoutClear {
211 fn default() -> Self {
212 LayoutClear::None
213 }
214}
215
216impl core::fmt::Debug for LayoutClear {
217 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
218 write!(f, "{}", self.print_as_css_value())
219 }
220}
221
222impl core::fmt::Display for LayoutClear {
223 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
224 write!(f, "{}", self.print_as_css_value())
225 }
226}
227
228impl PrintAsCssValue for LayoutClear {
229 fn print_as_css_value(&self) -> String {
230 match self {
231 LayoutClear::None => "none".to_string(),
232 LayoutClear::Left => "left".to_string(),
233 LayoutClear::Right => "right".to_string(),
234 LayoutClear::Both => "both".to_string(),
235 }
236 }
237}
238
239#[cfg(feature = "parser")]
240#[derive(Clone, PartialEq)]
241pub enum LayoutClearParseError<'a> {
242 InvalidValue(&'a str),
243}
244
245#[cfg(feature = "parser")]
246impl_debug_as_display!(LayoutClearParseError<'a>);
247#[cfg(feature = "parser")]
248impl_display! { LayoutClearParseError<'a>, {
249 InvalidValue(e) => format!("Invalid clear value: \"{}\"", e),
250}}
251
252#[cfg(feature = "parser")]
253#[derive(Debug, Clone, PartialEq)]
254pub enum LayoutClearParseErrorOwned {
255 InvalidValue(String),
256}
257
258#[cfg(feature = "parser")]
259impl<'a> LayoutClearParseError<'a> {
260 pub fn to_contained(&self) -> LayoutClearParseErrorOwned {
261 match self {
262 LayoutClearParseError::InvalidValue(s) => {
263 LayoutClearParseErrorOwned::InvalidValue(s.to_string())
264 }
265 }
266 }
267}
268
269#[cfg(feature = "parser")]
270impl LayoutClearParseErrorOwned {
271 pub fn to_shared<'a>(&'a self) -> LayoutClearParseError<'a> {
272 match self {
273 LayoutClearParseErrorOwned::InvalidValue(s) => {
274 LayoutClearParseError::InvalidValue(s.as_str())
275 }
276 }
277 }
278}
279
280#[cfg(feature = "parser")]
281pub fn parse_layout_clear<'a>(input: &'a str) -> Result<LayoutClear, LayoutClearParseError<'a>> {
282 let input = input.trim();
283 match input {
284 "none" => Ok(LayoutClear::None),
285 "left" => Ok(LayoutClear::Left),
286 "right" => Ok(LayoutClear::Right),
287 "both" => Ok(LayoutClear::Both),
288 _ => Err(LayoutClearParseError::InvalidValue(input)),
289 }
290}
291
292#[cfg(all(test, feature = "parser"))]
293mod tests {
294 use super::*;
295
296 #[test]
298 fn test_parse_layout_wrap_nowrap() {
299 assert_eq!(parse_layout_wrap("nowrap").unwrap(), LayoutWrap::NoWrap);
300 }
301
302 #[test]
303 fn test_parse_layout_wrap_wrap() {
304 assert_eq!(parse_layout_wrap("wrap").unwrap(), LayoutWrap::Wrap);
305 }
306
307 #[test]
308 fn test_parse_layout_wrap_wrap_reverse() {
309 assert_eq!(
310 parse_layout_wrap("wrap-reverse").unwrap(),
311 LayoutWrap::WrapReverse
312 );
313 }
314
315 #[test]
316 fn test_parse_layout_wrap_invalid() {
317 assert!(parse_layout_wrap("invalid").is_err());
318 }
319
320 #[test]
321 fn test_parse_layout_wrap_whitespace() {
322 assert_eq!(parse_layout_wrap(" wrap ").unwrap(), LayoutWrap::Wrap);
323 }
324
325 #[test]
326 fn test_parse_layout_wrap_case_sensitive() {
327 assert!(parse_layout_wrap("Wrap").is_err());
328 assert!(parse_layout_wrap("WRAP").is_err());
329 }
330
331 #[test]
333 fn test_parse_writing_mode_horizontal_tb() {
334 assert_eq!(
335 parse_layout_writing_mode("horizontal-tb").unwrap(),
336 LayoutWritingMode::HorizontalTb
337 );
338 }
339
340 #[test]
341 fn test_parse_writing_mode_vertical_rl() {
342 assert_eq!(
343 parse_layout_writing_mode("vertical-rl").unwrap(),
344 LayoutWritingMode::VerticalRl
345 );
346 }
347
348 #[test]
349 fn test_parse_writing_mode_vertical_lr() {
350 assert_eq!(
351 parse_layout_writing_mode("vertical-lr").unwrap(),
352 LayoutWritingMode::VerticalLr
353 );
354 }
355
356 #[test]
357 fn test_parse_writing_mode_invalid() {
358 assert!(parse_layout_writing_mode("invalid").is_err());
359 assert!(parse_layout_writing_mode("horizontal").is_err());
360 }
361
362 #[test]
363 fn test_parse_writing_mode_whitespace() {
364 assert_eq!(
365 parse_layout_writing_mode(" vertical-rl ").unwrap(),
366 LayoutWritingMode::VerticalRl
367 );
368 }
369
370 #[test]
372 fn test_parse_layout_clear_none() {
373 assert_eq!(parse_layout_clear("none").unwrap(), LayoutClear::None);
374 }
375
376 #[test]
377 fn test_parse_layout_clear_left() {
378 assert_eq!(parse_layout_clear("left").unwrap(), LayoutClear::Left);
379 }
380
381 #[test]
382 fn test_parse_layout_clear_right() {
383 assert_eq!(parse_layout_clear("right").unwrap(), LayoutClear::Right);
384 }
385
386 #[test]
387 fn test_parse_layout_clear_both() {
388 assert_eq!(parse_layout_clear("both").unwrap(), LayoutClear::Both);
389 }
390
391 #[test]
392 fn test_parse_layout_clear_invalid() {
393 assert!(parse_layout_clear("invalid").is_err());
394 assert!(parse_layout_clear("all").is_err());
395 }
396
397 #[test]
398 fn test_parse_layout_clear_whitespace() {
399 assert_eq!(parse_layout_clear(" both ").unwrap(), LayoutClear::Both);
400 }
401
402 #[test]
404 fn test_print_layout_wrap() {
405 assert_eq!(LayoutWrap::NoWrap.print_as_css_value(), "nowrap");
406 assert_eq!(LayoutWrap::Wrap.print_as_css_value(), "wrap");
407 assert_eq!(LayoutWrap::WrapReverse.print_as_css_value(), "wrap-reverse");
408 }
409
410 #[test]
411 fn test_print_writing_mode() {
412 assert_eq!(
413 LayoutWritingMode::HorizontalTb.print_as_css_value(),
414 "horizontal-tb"
415 );
416 assert_eq!(
417 LayoutWritingMode::VerticalRl.print_as_css_value(),
418 "vertical-rl"
419 );
420 assert_eq!(
421 LayoutWritingMode::VerticalLr.print_as_css_value(),
422 "vertical-lr"
423 );
424 }
425
426 #[test]
427 fn test_print_layout_clear() {
428 assert_eq!(LayoutClear::None.print_as_css_value(), "none");
429 assert_eq!(LayoutClear::Left.print_as_css_value(), "left");
430 assert_eq!(LayoutClear::Right.print_as_css_value(), "right");
431 assert_eq!(LayoutClear::Both.print_as_css_value(), "both");
432 }
433}