1use alloc::string::{String, ToString};
8use core::num::ParseIntError;
9
10use crate::props::{
11 basic::{
12 color::{parse_css_color, ColorU, CssColorParseError, CssColorParseErrorOwned},
13 pixel::{
14 parse_pixel_value, CssPixelValueParseError, CssPixelValueParseErrorOwned, PixelValue,
15 },
16 },
17 formatter::PrintAsCssValue,
18 style::border::{
19 parse_border_style, BorderStyle, CssBorderStyleParseError, CssBorderStyleParseErrorOwned,
20 },
21};
22
23#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
29#[repr(C, u8)]
30#[derive(Default)]
31pub enum ColumnCount {
32 #[default]
33 Auto,
34 Integer(u32),
35}
36
37
38impl PrintAsCssValue for ColumnCount {
39 fn print_as_css_value(&self) -> String {
40 match self {
41 Self::Auto => "auto".to_string(),
42 Self::Integer(i) => i.to_string(),
43 }
44 }
45}
46
47#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
53#[repr(C, u8)]
54#[derive(Default)]
55pub enum ColumnWidth {
56 #[default]
57 Auto,
58 Length(PixelValue),
59}
60
61
62impl PrintAsCssValue for ColumnWidth {
63 fn print_as_css_value(&self) -> String {
64 match self {
65 Self::Auto => "auto".to_string(),
66 Self::Length(px) => px.print_as_css_value(),
67 }
68 }
69}
70
71#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
77#[repr(C)]
78#[derive(Default)]
79pub enum ColumnSpan {
80 #[default]
81 None,
82 All,
83}
84
85
86impl PrintAsCssValue for ColumnSpan {
87 fn print_as_css_value(&self) -> String {
88 String::from(match self {
89 Self::None => "none",
90 Self::All => "all",
91 })
92 }
93}
94
95#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
101#[repr(C)]
102#[derive(Default)]
103pub enum ColumnFill {
104 Auto,
105 #[default]
106 Balance,
107}
108
109
110impl PrintAsCssValue for ColumnFill {
111 fn print_as_css_value(&self) -> String {
112 String::from(match self {
113 Self::Auto => "auto",
114 Self::Balance => "balance",
115 })
116 }
117}
118
119#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
125#[repr(C)]
126pub struct ColumnRuleWidth {
127 pub inner: PixelValue,
128}
129
130impl Default for ColumnRuleWidth {
131 fn default() -> Self {
132 Self {
133 inner: PixelValue::const_px(3),
134 }
135 }
136}
137
138impl PrintAsCssValue for ColumnRuleWidth {
139 fn print_as_css_value(&self) -> String {
140 self.inner.print_as_css_value()
141 }
142}
143
144#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
148#[repr(C)]
149pub struct ColumnRuleStyle {
150 pub inner: BorderStyle,
151}
152
153impl Default for ColumnRuleStyle {
154 fn default() -> Self {
155 Self {
156 inner: BorderStyle::None,
157 }
158 }
159}
160
161impl PrintAsCssValue for ColumnRuleStyle {
162 fn print_as_css_value(&self) -> String {
163 self.inner.print_as_css_value()
164 }
165}
166
167#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
173#[repr(C)]
174pub struct ColumnRuleColor {
175 pub inner: ColorU,
176}
177
178impl Default for ColumnRuleColor {
179 fn default() -> Self {
180 Self {
182 inner: ColorU::BLACK,
183 }
184 }
185}
186
187impl PrintAsCssValue for ColumnRuleColor {
188 fn print_as_css_value(&self) -> String {
189 self.inner.to_hash()
190 }
191}
192
193impl crate::format_rust_code::FormatAsRustCode for ColumnCount {
195 fn format_as_rust_code(&self, _tabs: usize) -> String {
196 match self {
197 ColumnCount::Auto => String::from("ColumnCount::Auto"),
198 ColumnCount::Integer(i) => format!("ColumnCount::Integer({})", i),
199 }
200 }
201}
202
203impl crate::format_rust_code::FormatAsRustCode for ColumnWidth {
204 fn format_as_rust_code(&self, _tabs: usize) -> String {
205 match self {
206 ColumnWidth::Auto => String::from("ColumnWidth::Auto"),
207 ColumnWidth::Length(px) => format!(
208 "ColumnWidth::Length({})",
209 crate::format_rust_code::format_pixel_value(px)
210 ),
211 }
212 }
213}
214
215impl crate::format_rust_code::FormatAsRustCode for ColumnSpan {
216 fn format_as_rust_code(&self, _tabs: usize) -> String {
217 match self {
218 ColumnSpan::None => String::from("ColumnSpan::None"),
219 ColumnSpan::All => String::from("ColumnSpan::All"),
220 }
221 }
222}
223
224impl crate::format_rust_code::FormatAsRustCode for ColumnFill {
225 fn format_as_rust_code(&self, _tabs: usize) -> String {
226 match self {
227 ColumnFill::Auto => String::from("ColumnFill::Auto"),
228 ColumnFill::Balance => String::from("ColumnFill::Balance"),
229 }
230 }
231}
232
233impl crate::format_rust_code::FormatAsRustCode for ColumnRuleWidth {
234 fn format_as_rust_code(&self, _tabs: usize) -> String {
235 format!(
236 "ColumnRuleWidth {{ inner: {} }}",
237 crate::format_rust_code::format_pixel_value(&self.inner)
238 )
239 }
240}
241
242impl crate::format_rust_code::FormatAsRustCode for ColumnRuleStyle {
243 fn format_as_rust_code(&self, tabs: usize) -> String {
244 format!(
245 "ColumnRuleStyle {{ inner: {} }}",
246 self.inner.format_as_rust_code(tabs)
247 )
248 }
249}
250
251impl crate::format_rust_code::FormatAsRustCode for ColumnRuleColor {
252 fn format_as_rust_code(&self, _tabs: usize) -> String {
253 format!(
254 "ColumnRuleColor {{ inner: {} }}",
255 crate::format_rust_code::format_color_value(&self.inner)
256 )
257 }
258}
259
260#[cfg(feature = "parser")]
263pub mod parser {
264 use super::*;
265 use crate::corety::AzString;
266
267 #[derive(Clone, PartialEq)]
270 pub enum ColumnCountParseError<'a> {
271 InvalidValue(&'a str),
272 ParseInt(ParseIntError),
273 }
274
275 impl_debug_as_display!(ColumnCountParseError<'a>);
276 impl_display! { ColumnCountParseError<'a>, {
277 InvalidValue(v) => format!("Invalid column-count value: \"{}\"", v),
278 ParseInt(e) => format!("Invalid integer for column-count: {}", e),
279 }}
280
281 #[derive(Debug, Clone, PartialEq)]
282 #[repr(C, u8)]
283 pub enum ColumnCountParseErrorOwned {
284 InvalidValue(AzString),
285 ParseInt(AzString),
286 }
287
288 impl<'a> ColumnCountParseError<'a> {
289 pub fn to_contained(&self) -> ColumnCountParseErrorOwned {
290 match self {
291 Self::InvalidValue(s) => ColumnCountParseErrorOwned::InvalidValue(s.to_string().into()),
292 Self::ParseInt(e) => ColumnCountParseErrorOwned::ParseInt(e.to_string().into()),
293 }
294 }
295 }
296
297 impl ColumnCountParseErrorOwned {
298 pub fn to_shared<'a>(&'a self) -> ColumnCountParseError<'a> {
299 match self {
300 Self::InvalidValue(s) => ColumnCountParseError::InvalidValue(s),
301 Self::ParseInt(_) => ColumnCountParseError::InvalidValue("invalid integer"),
305 }
306 }
307 }
308
309 pub fn parse_column_count<'a>(
310 input: &'a str,
311 ) -> Result<ColumnCount, ColumnCountParseError<'a>> {
312 let trimmed = input.trim();
313 if trimmed == "auto" {
314 return Ok(ColumnCount::Auto);
315 }
316 let val: u32 = trimmed
317 .parse()
318 .map_err(ColumnCountParseError::ParseInt)?;
319 Ok(ColumnCount::Integer(val))
320 }
321
322 #[derive(Clone, PartialEq)]
325 pub enum ColumnWidthParseError<'a> {
326 InvalidValue(&'a str),
327 PixelValue(CssPixelValueParseError<'a>),
328 }
329
330 impl_debug_as_display!(ColumnWidthParseError<'a>);
331 impl_display! { ColumnWidthParseError<'a>, {
332 InvalidValue(v) => format!("Invalid column-width value: \"{}\"", v),
333 PixelValue(e) => format!("{}", e),
334 }}
335 impl_from! { CssPixelValueParseError<'a>, ColumnWidthParseError::PixelValue }
336
337 #[derive(Debug, Clone, PartialEq)]
338 #[repr(C, u8)]
339 pub enum ColumnWidthParseErrorOwned {
340 InvalidValue(AzString),
341 PixelValue(CssPixelValueParseErrorOwned),
342 }
343
344 impl<'a> ColumnWidthParseError<'a> {
345 pub fn to_contained(&self) -> ColumnWidthParseErrorOwned {
346 match self {
347 Self::InvalidValue(s) => ColumnWidthParseErrorOwned::InvalidValue(s.to_string().into()),
348 Self::PixelValue(e) => ColumnWidthParseErrorOwned::PixelValue(e.to_contained()),
349 }
350 }
351 }
352
353 impl ColumnWidthParseErrorOwned {
354 pub fn to_shared<'a>(&'a self) -> ColumnWidthParseError<'a> {
355 match self {
356 Self::InvalidValue(s) => ColumnWidthParseError::InvalidValue(s),
357 Self::PixelValue(e) => ColumnWidthParseError::PixelValue(e.to_shared()),
358 }
359 }
360 }
361
362 pub fn parse_column_width<'a>(
363 input: &'a str,
364 ) -> Result<ColumnWidth, ColumnWidthParseError<'a>> {
365 let trimmed = input.trim();
366 if trimmed == "auto" {
367 return Ok(ColumnWidth::Auto);
368 }
369 Ok(ColumnWidth::Length(parse_pixel_value(trimmed)?))
370 }
371
372 macro_rules! define_simple_column_parser {
374 (
375 $fn_name:ident,
376 $struct_name:ident,
377 $error_name:ident,
378 $error_owned_name:ident,
379 $prop_name:expr,
380 $($val:expr => $variant:path),+
381 ) => {
382 #[derive(Clone, PartialEq)]
383 pub enum $error_name<'a> {
384 InvalidValue(&'a str),
385 }
386
387 impl_debug_as_display!($error_name<'a>);
388 impl_display! { $error_name<'a>, {
389 InvalidValue(v) => format!("Invalid {} value: \"{}\"", $prop_name, v),
390 }}
391
392 #[derive(Debug, Clone, PartialEq)]
393 #[repr(C, u8)]
394 pub enum $error_owned_name {
395 InvalidValue(AzString),
396 }
397
398 impl<'a> $error_name<'a> {
399 pub fn to_contained(&self) -> $error_owned_name {
400 match self {
401 Self::InvalidValue(s) => $error_owned_name::InvalidValue(s.to_string().into()),
402 }
403 }
404 }
405
406 impl $error_owned_name {
407 pub fn to_shared<'a>(&'a self) -> $error_name<'a> {
408 match self {
409 Self::InvalidValue(s) => $error_name::InvalidValue(s.as_str()),
410 }
411 }
412 }
413
414 pub fn $fn_name<'a>(input: &'a str) -> Result<$struct_name, $error_name<'a>> {
415 match input.trim() {
416 $( $val => Ok($variant), )+
417 _ => Err($error_name::InvalidValue(input)),
418 }
419 }
420 };
421 }
422
423 define_simple_column_parser!(
424 parse_column_span,
425 ColumnSpan,
426 ColumnSpanParseError,
427 ColumnSpanParseErrorOwned,
428 "column-span",
429 "none" => ColumnSpan::None,
430 "all" => ColumnSpan::All
431 );
432
433 define_simple_column_parser!(
434 parse_column_fill,
435 ColumnFill,
436 ColumnFillParseError,
437 ColumnFillParseErrorOwned,
438 "column-fill",
439 "auto" => ColumnFill::Auto,
440 "balance" => ColumnFill::Balance
441 );
442
443 #[derive(Clone, PartialEq)]
446 pub enum ColumnRuleWidthParseError<'a> {
447 Pixel(CssPixelValueParseError<'a>),
448 }
449 impl_debug_as_display!(ColumnRuleWidthParseError<'a>);
450 impl_display! { ColumnRuleWidthParseError<'a>, { Pixel(e) => format!("{}", e) }}
451 impl_from! { CssPixelValueParseError<'a>, ColumnRuleWidthParseError::Pixel }
452 #[derive(Debug, Clone, PartialEq)]
453 #[repr(C, u8)]
454 pub enum ColumnRuleWidthParseErrorOwned {
455 Pixel(CssPixelValueParseErrorOwned),
456 }
457 impl<'a> ColumnRuleWidthParseError<'a> {
458 pub fn to_contained(&self) -> ColumnRuleWidthParseErrorOwned {
459 match self {
460 ColumnRuleWidthParseError::Pixel(e) => {
461 ColumnRuleWidthParseErrorOwned::Pixel(e.to_contained())
462 }
463 }
464 }
465 }
466 impl ColumnRuleWidthParseErrorOwned {
467 pub fn to_shared<'a>(&'a self) -> ColumnRuleWidthParseError<'a> {
468 match self {
469 ColumnRuleWidthParseErrorOwned::Pixel(e) => {
470 ColumnRuleWidthParseError::Pixel(e.to_shared())
471 }
472 }
473 }
474 }
475 pub fn parse_column_rule_width<'a>(
476 input: &'a str,
477 ) -> Result<ColumnRuleWidth, ColumnRuleWidthParseError<'a>> {
478 Ok(ColumnRuleWidth {
479 inner: parse_pixel_value(input)?,
480 })
481 }
482
483 #[derive(Clone, PartialEq)]
484 pub enum ColumnRuleStyleParseError<'a> {
485 Style(CssBorderStyleParseError<'a>),
486 }
487 impl_debug_as_display!(ColumnRuleStyleParseError<'a>);
488 impl_display! { ColumnRuleStyleParseError<'a>, { Style(e) => format!("{}", e) }}
489 impl_from! { CssBorderStyleParseError<'a>, ColumnRuleStyleParseError::Style }
490 #[derive(Debug, Clone, PartialEq)]
491 #[repr(C, u8)]
492 pub enum ColumnRuleStyleParseErrorOwned {
493 Style(CssBorderStyleParseErrorOwned),
494 }
495 impl<'a> ColumnRuleStyleParseError<'a> {
496 pub fn to_contained(&self) -> ColumnRuleStyleParseErrorOwned {
497 match self {
498 ColumnRuleStyleParseError::Style(e) => {
499 ColumnRuleStyleParseErrorOwned::Style(e.to_contained())
500 }
501 }
502 }
503 }
504 impl ColumnRuleStyleParseErrorOwned {
505 pub fn to_shared<'a>(&'a self) -> ColumnRuleStyleParseError<'a> {
506 match self {
507 ColumnRuleStyleParseErrorOwned::Style(e) => {
508 ColumnRuleStyleParseError::Style(e.to_shared())
509 }
510 }
511 }
512 }
513 pub fn parse_column_rule_style<'a>(
514 input: &'a str,
515 ) -> Result<ColumnRuleStyle, ColumnRuleStyleParseError<'a>> {
516 Ok(ColumnRuleStyle {
517 inner: parse_border_style(input)?,
518 })
519 }
520
521 #[derive(Clone, PartialEq)]
522 pub enum ColumnRuleColorParseError<'a> {
523 Color(CssColorParseError<'a>),
524 }
525 impl_debug_as_display!(ColumnRuleColorParseError<'a>);
526 impl_display! { ColumnRuleColorParseError<'a>, { Color(e) => format!("{}", e) }}
527 impl_from! { CssColorParseError<'a>, ColumnRuleColorParseError::Color }
528 #[derive(Debug, Clone, PartialEq)]
529 #[repr(C, u8)]
530 pub enum ColumnRuleColorParseErrorOwned {
531 Color(CssColorParseErrorOwned),
532 }
533 impl<'a> ColumnRuleColorParseError<'a> {
534 pub fn to_contained(&self) -> ColumnRuleColorParseErrorOwned {
535 match self {
536 ColumnRuleColorParseError::Color(e) => {
537 ColumnRuleColorParseErrorOwned::Color(e.to_contained())
538 }
539 }
540 }
541 }
542 impl ColumnRuleColorParseErrorOwned {
543 pub fn to_shared<'a>(&'a self) -> ColumnRuleColorParseError<'a> {
544 match self {
545 ColumnRuleColorParseErrorOwned::Color(e) => {
546 ColumnRuleColorParseError::Color(e.to_shared())
547 }
548 }
549 }
550 }
551 pub fn parse_column_rule_color<'a>(
552 input: &'a str,
553 ) -> Result<ColumnRuleColor, ColumnRuleColorParseError<'a>> {
554 Ok(ColumnRuleColor {
555 inner: parse_css_color(input)?,
556 })
557 }
558}
559
560#[cfg(feature = "parser")]
561pub use parser::*;
562
563#[cfg(all(test, feature = "parser"))]
564mod tests {
565 use super::*;
566
567 #[test]
568 fn test_parse_column_count() {
569 assert_eq!(parse_column_count("auto").unwrap(), ColumnCount::Auto);
570 assert_eq!(parse_column_count("3").unwrap(), ColumnCount::Integer(3));
571 assert!(parse_column_count("none").is_err());
572 assert!(parse_column_count("2.5").is_err());
573 }
574
575 #[test]
576 fn test_parse_column_width() {
577 assert_eq!(parse_column_width("auto").unwrap(), ColumnWidth::Auto);
578 assert_eq!(
579 parse_column_width("200px").unwrap(),
580 ColumnWidth::Length(PixelValue::px(200.0))
581 );
582 assert_eq!(
583 parse_column_width("15em").unwrap(),
584 ColumnWidth::Length(PixelValue::em(15.0))
585 );
586 assert!(parse_column_width("50%").is_ok()); }
588
589 #[test]
590 fn test_parse_column_span() {
591 assert_eq!(parse_column_span("none").unwrap(), ColumnSpan::None);
592 assert_eq!(parse_column_span("all").unwrap(), ColumnSpan::All);
593 assert!(parse_column_span("2").is_err());
594 }
595
596 #[test]
597 fn test_parse_column_fill() {
598 assert_eq!(parse_column_fill("auto").unwrap(), ColumnFill::Auto);
599 assert_eq!(parse_column_fill("balance").unwrap(), ColumnFill::Balance);
600 assert!(parse_column_fill("none").is_err());
601 }
602
603 #[test]
604 fn test_parse_column_rule() {
605 assert_eq!(
606 parse_column_rule_width("5px").unwrap().inner,
607 PixelValue::px(5.0)
608 );
609 assert_eq!(
610 parse_column_rule_style("dotted").unwrap().inner,
611 BorderStyle::Dotted
612 );
613 assert_eq!(parse_column_rule_color("blue").unwrap().inner, ColorU::BLUE);
614 }
615}