1use alloc::string::{String, ToString};
4use core::num::ParseFloatError;
5use crate::corety::AzString;
6
7use crate::{
8 codegen::format::FormatAsRustCode,
9 props::{
10 basic::{
11 error::ParseFloatErrorWithInput,
12 length::{parse_float_value, FloatValue},
13 },
14 formatter::PrintAsCssValue,
15 },
16};
17
18#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[repr(C)]
25pub struct LayoutFlexGrow {
26 pub inner: FloatValue,
27}
28
29impl core::fmt::Debug for LayoutFlexGrow {
30 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
31 write!(f, "{}", self.inner.get())
32 }
33}
34
35impl Default for LayoutFlexGrow {
36 fn default() -> Self {
37 Self {
38 inner: FloatValue::const_new(0),
39 }
40 }
41}
42
43impl PrintAsCssValue for LayoutFlexGrow {
44 fn print_as_css_value(&self) -> String {
45 format!("{}", self.inner)
46 }
47}
48
49impl LayoutFlexGrow {
50 #[must_use] pub fn new(value: isize) -> Self {
51 Self {
52 inner: FloatValue::new(crate::cast::isize_to_f32(value)),
53 }
54 }
55
56 #[must_use] pub const fn const_new(value: isize) -> Self {
57 Self {
58 inner: FloatValue::const_new(value),
59 }
60 }
61
62 #[must_use] pub fn interpolate(&self, other: &Self, t: f32) -> Self {
63 Self {
64 inner: self.inner.interpolate(&other.inner, t),
65 }
66 }
67}
68
69#[cfg(feature = "parser")]
70#[derive(Clone, PartialEq, Eq)]
71pub enum FlexGrowParseError<'a> {
72 ParseFloat(ParseFloatError, &'a str),
73 NegativeValue(&'a str),
74}
75
76#[cfg(feature = "parser")]
77impl_debug_as_display!(FlexGrowParseError<'a>);
78#[cfg(feature = "parser")]
79impl_display! { FlexGrowParseError<'a>, {
80 ParseFloat(e, s) => format!("Invalid flex-grow value: \"{}\". Reason: {}", s, e),
81 NegativeValue(s) => format!("Invalid flex-grow value: \"{}\". Flex-grow cannot be negative", s),
82}}
83
84#[cfg(feature = "parser")]
85#[derive(Debug, Clone, PartialEq, Eq)]
86#[repr(C, u8)]
87pub enum FlexGrowParseErrorOwned {
88 ParseFloat(ParseFloatErrorWithInput),
89 NegativeValue(AzString),
90}
91
92#[cfg(feature = "parser")]
93impl FlexGrowParseError<'_> {
94 #[must_use] pub fn to_contained(&self) -> FlexGrowParseErrorOwned {
95 match self {
96 FlexGrowParseError::ParseFloat(e, s) => {
97 FlexGrowParseErrorOwned::ParseFloat(ParseFloatErrorWithInput { error: e.clone().into(), input: (*s).to_string().into() })
98 }
99 FlexGrowParseError::NegativeValue(s) => {
100 FlexGrowParseErrorOwned::NegativeValue((*s).to_string().into())
101 }
102 }
103 }
104}
105
106#[cfg(feature = "parser")]
107impl FlexGrowParseErrorOwned {
108 #[must_use] pub fn to_shared(&self) -> FlexGrowParseError<'_> {
109 match self {
110 Self::ParseFloat(e) => {
111 FlexGrowParseError::ParseFloat(e.error.to_std(), e.input.as_str())
112 }
113 Self::NegativeValue(s) => {
114 FlexGrowParseError::NegativeValue(s.as_str())
115 }
116 }
117 }
118}
119
120#[cfg(feature = "parser")]
121pub fn parse_layout_flex_grow(
125 input: &str,
126) -> Result<LayoutFlexGrow, FlexGrowParseError<'_>> {
127 match parse_float_value(input) {
128 Ok(o) => {
129 if o.get() < 0.0 {
130 Err(FlexGrowParseError::NegativeValue(input))
131 } else {
132 Ok(LayoutFlexGrow { inner: o })
133 }
134 }
135 Err(e) => Err(FlexGrowParseError::ParseFloat(e, input)),
136 }
137}
138
139#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
145#[repr(C)]
146pub struct LayoutFlexShrink {
147 pub inner: FloatValue,
148}
149
150impl core::fmt::Debug for LayoutFlexShrink {
151 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
152 write!(f, "{}", self.inner.get())
153 }
154}
155
156impl Default for LayoutFlexShrink {
157 fn default() -> Self {
158 Self {
159 inner: FloatValue::const_new(1),
160 }
161 }
162}
163
164impl PrintAsCssValue for LayoutFlexShrink {
165 fn print_as_css_value(&self) -> String {
166 format!("{}", self.inner)
167 }
168}
169
170impl LayoutFlexShrink {
171 #[must_use] pub fn interpolate(&self, other: &Self, t: f32) -> Self {
172 Self {
173 inner: self.inner.interpolate(&other.inner, t),
174 }
175 }
176}
177
178#[cfg(feature = "parser")]
179#[derive(Clone, PartialEq, Eq)]
180pub enum FlexShrinkParseError<'a> {
181 ParseFloat(ParseFloatError, &'a str),
182 NegativeValue(&'a str),
183}
184
185#[cfg(feature = "parser")]
186impl_debug_as_display!(FlexShrinkParseError<'a>);
187#[cfg(feature = "parser")]
188impl_display! { FlexShrinkParseError<'a>, {
189 ParseFloat(e, s) => format!("Invalid flex-shrink value: \"{}\". Reason: {}", s, e),
190 NegativeValue(s) => format!("Invalid flex-shrink value: \"{}\". Flex-shrink cannot be negative", s),
191}}
192
193#[cfg(feature = "parser")]
194#[derive(Debug, Clone, PartialEq, Eq)]
195#[repr(C, u8)]
196pub enum FlexShrinkParseErrorOwned {
197 ParseFloat(ParseFloatErrorWithInput),
198 NegativeValue(AzString),
199}
200
201#[cfg(feature = "parser")]
202impl FlexShrinkParseError<'_> {
203 #[must_use] pub fn to_contained(&self) -> FlexShrinkParseErrorOwned {
204 match self {
205 FlexShrinkParseError::ParseFloat(e, s) => {
206 FlexShrinkParseErrorOwned::ParseFloat(ParseFloatErrorWithInput { error: e.clone().into(), input: (*s).to_string().into() })
207 }
208 FlexShrinkParseError::NegativeValue(s) => {
209 FlexShrinkParseErrorOwned::NegativeValue((*s).to_string().into())
210 }
211 }
212 }
213}
214
215#[cfg(feature = "parser")]
216impl FlexShrinkParseErrorOwned {
217 #[must_use] pub fn to_shared(&self) -> FlexShrinkParseError<'_> {
218 match self {
219 Self::ParseFloat(e) => {
220 FlexShrinkParseError::ParseFloat(e.error.to_std(), e.input.as_str())
221 }
222 Self::NegativeValue(s) => {
223 FlexShrinkParseError::NegativeValue(s.as_str())
224 }
225 }
226 }
227}
228
229#[cfg(feature = "parser")]
230pub fn parse_layout_flex_shrink(
234 input: &str,
235) -> Result<LayoutFlexShrink, FlexShrinkParseError<'_>> {
236 match parse_float_value(input) {
237 Ok(o) => {
238 if o.get() < 0.0 {
239 Err(FlexShrinkParseError::NegativeValue(input))
240 } else {
241 Ok(LayoutFlexShrink { inner: o })
242 }
243 }
244 Err(e) => Err(FlexShrinkParseError::ParseFloat(e, input)),
245 }
246}
247
248#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
254#[repr(C)]
255#[derive(Default)]
256pub enum LayoutFlexDirection {
257 #[default]
258 Row,
259 RowReverse,
260 Column,
261 ColumnReverse,
262}
263
264
265#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
267#[repr(C)]
268pub enum LayoutAxis {
269 Horizontal,
270 Vertical,
271}
272
273impl LayoutFlexDirection {
274 #[must_use] pub const fn get_axis(&self) -> LayoutAxis {
275 match self {
276 Self::Row | Self::RowReverse => LayoutAxis::Horizontal,
277 Self::Column | Self::ColumnReverse => LayoutAxis::Vertical,
278 }
279 }
280
281 #[must_use] pub const fn is_reverse(&self) -> bool {
282 matches!(self, Self::RowReverse | Self::ColumnReverse)
283 }
284}
285
286impl PrintAsCssValue for LayoutFlexDirection {
287 fn print_as_css_value(&self) -> String {
288 String::from(match self {
289 Self::Row => "row",
290 Self::RowReverse => "row-reverse",
291 Self::Column => "column",
292 Self::ColumnReverse => "column-reverse",
293 })
294 }
295}
296
297#[cfg(feature = "parser")]
298#[derive(Clone, PartialEq, Eq)]
299pub enum FlexDirectionParseError<'a> {
300 InvalidValue(&'a str),
301}
302
303#[cfg(feature = "parser")]
304impl_debug_as_display!(FlexDirectionParseError<'a>);
305#[cfg(feature = "parser")]
306impl_display! { FlexDirectionParseError<'a>, {
307 InvalidValue(s) => format!("Invalid flex-direction value: \"{}\"", s),
308}}
309
310#[cfg(feature = "parser")]
311#[derive(Debug, Clone, PartialEq, Eq)]
312#[repr(C, u8)]
313pub enum FlexDirectionParseErrorOwned {
314 InvalidValue(AzString),
315}
316
317#[cfg(feature = "parser")]
318impl FlexDirectionParseError<'_> {
319 #[must_use] pub fn to_contained(&self) -> FlexDirectionParseErrorOwned {
320 match self {
321 Self::InvalidValue(s) => FlexDirectionParseErrorOwned::InvalidValue((*s).to_string().into()),
322 }
323 }
324}
325
326#[cfg(feature = "parser")]
327impl FlexDirectionParseErrorOwned {
328 #[must_use] pub fn to_shared(&self) -> FlexDirectionParseError<'_> {
329 match self {
330 Self::InvalidValue(s) => FlexDirectionParseError::InvalidValue(s.as_str()),
331 }
332 }
333}
334
335#[cfg(feature = "parser")]
336pub fn parse_layout_flex_direction(
340 input: &str,
341) -> Result<LayoutFlexDirection, FlexDirectionParseError<'_>> {
342 match input.trim() {
343 "row" => Ok(LayoutFlexDirection::Row),
344 "row-reverse" => Ok(LayoutFlexDirection::RowReverse),
345 "column" => Ok(LayoutFlexDirection::Column),
346 "column-reverse" => Ok(LayoutFlexDirection::ColumnReverse),
347 _ => Err(FlexDirectionParseError::InvalidValue(input)),
348 }
349}
350
351#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
357#[repr(C)]
358#[derive(Default)]
359pub enum LayoutFlexWrap {
360 Wrap,
361 #[default]
362 NoWrap,
363 WrapReverse,
364}
365
366
367impl PrintAsCssValue for LayoutFlexWrap {
368 fn print_as_css_value(&self) -> String {
369 String::from(match self {
370 Self::Wrap => "wrap",
371 Self::NoWrap => "nowrap",
372 Self::WrapReverse => "wrap-reverse",
373 })
374 }
375}
376
377#[cfg(feature = "parser")]
378#[derive(Clone, PartialEq, Eq)]
379pub enum FlexWrapParseError<'a> {
380 InvalidValue(&'a str),
381}
382
383#[cfg(feature = "parser")]
384impl_debug_as_display!(FlexWrapParseError<'a>);
385#[cfg(feature = "parser")]
386impl_display! { FlexWrapParseError<'a>, {
387 InvalidValue(s) => format!("Invalid flex-wrap value: \"{}\"", s),
388}}
389
390#[cfg(feature = "parser")]
391#[derive(Debug, Clone, PartialEq, Eq)]
392#[repr(C, u8)]
393pub enum FlexWrapParseErrorOwned {
394 InvalidValue(AzString),
395}
396
397#[cfg(feature = "parser")]
398impl FlexWrapParseError<'_> {
399 #[must_use] pub fn to_contained(&self) -> FlexWrapParseErrorOwned {
400 match self {
401 Self::InvalidValue(s) => FlexWrapParseErrorOwned::InvalidValue((*s).to_string().into()),
402 }
403 }
404}
405
406#[cfg(feature = "parser")]
407impl FlexWrapParseErrorOwned {
408 #[must_use] pub fn to_shared(&self) -> FlexWrapParseError<'_> {
409 match self {
410 Self::InvalidValue(s) => FlexWrapParseError::InvalidValue(s.as_str()),
411 }
412 }
413}
414
415#[cfg(feature = "parser")]
416pub fn parse_layout_flex_wrap(
420 input: &str,
421) -> Result<LayoutFlexWrap, FlexWrapParseError<'_>> {
422 match input.trim() {
423 "wrap" => Ok(LayoutFlexWrap::Wrap),
424 "nowrap" => Ok(LayoutFlexWrap::NoWrap),
425 "wrap-reverse" => Ok(LayoutFlexWrap::WrapReverse),
426 _ => Err(FlexWrapParseError::InvalidValue(input)),
427 }
428}
429
430#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
436#[repr(C)]
437#[derive(Default)]
438pub enum LayoutJustifyContent {
439 FlexStart,
440 FlexEnd,
441 #[default]
442 Start,
443 End,
444 Center,
445 SpaceBetween,
446 SpaceAround,
447 SpaceEvenly,
448}
449
450
451impl PrintAsCssValue for LayoutJustifyContent {
452 fn print_as_css_value(&self) -> String {
453 String::from(match self {
454 Self::Start => "start",
455 Self::End => "end",
456 Self::FlexStart => "flex-start",
457 Self::FlexEnd => "flex-end",
458 Self::Center => "center",
459 Self::SpaceBetween => "space-between",
460 Self::SpaceAround => "space-around",
461 Self::SpaceEvenly => "space-evenly",
462 })
463 }
464}
465
466#[cfg(feature = "parser")]
467#[derive(Clone, PartialEq, Eq)]
468pub enum JustifyContentParseError<'a> {
469 InvalidValue(&'a str),
470}
471
472#[cfg(feature = "parser")]
473impl_debug_as_display!(JustifyContentParseError<'a>);
474#[cfg(feature = "parser")]
475impl_display! { JustifyContentParseError<'a>, {
476 InvalidValue(s) => format!("Invalid justify-content value: \"{}\"", s),
477}}
478
479#[cfg(feature = "parser")]
480#[derive(Debug, Clone, PartialEq, Eq)]
481#[repr(C, u8)]
482pub enum JustifyContentParseErrorOwned {
483 InvalidValue(AzString),
484}
485
486#[cfg(feature = "parser")]
487impl JustifyContentParseError<'_> {
488 #[must_use] pub fn to_contained(&self) -> JustifyContentParseErrorOwned {
489 match self {
490 Self::InvalidValue(s) => JustifyContentParseErrorOwned::InvalidValue((*s).to_string().into()),
491 }
492 }
493}
494
495#[cfg(feature = "parser")]
496impl JustifyContentParseErrorOwned {
497 #[must_use] pub fn to_shared(&self) -> JustifyContentParseError<'_> {
498 match self {
499 Self::InvalidValue(s) => JustifyContentParseError::InvalidValue(s.as_str()),
500 }
501 }
502}
503
504#[cfg(feature = "parser")]
505pub fn parse_layout_justify_content(
509 input: &str,
510) -> Result<LayoutJustifyContent, JustifyContentParseError<'_>> {
511 match input.trim() {
512 "flex-start" => Ok(LayoutJustifyContent::FlexStart),
513 "flex-end" => Ok(LayoutJustifyContent::FlexEnd),
514 "start" => Ok(LayoutJustifyContent::Start),
515 "end" => Ok(LayoutJustifyContent::End),
516 "center" => Ok(LayoutJustifyContent::Center),
517 "space-between" => Ok(LayoutJustifyContent::SpaceBetween),
518 "space-around" => Ok(LayoutJustifyContent::SpaceAround),
519 "space-evenly" => Ok(LayoutJustifyContent::SpaceEvenly),
520 _ => Err(JustifyContentParseError::InvalidValue(input)),
521 }
522}
523
524#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
530#[repr(C)]
531#[derive(Default)]
532pub enum LayoutAlignItems {
533 #[default]
534 Stretch,
535 Center,
536 Start,
537 End,
538 Baseline,
539}
540
541
542impl PrintAsCssValue for LayoutAlignItems {
543 fn print_as_css_value(&self) -> String {
544 String::from(match self {
545 Self::Stretch => "stretch",
546 Self::Center => "center",
547 Self::Start => "flex-start",
548 Self::End => "flex-end",
549 Self::Baseline => "baseline",
550 })
551 }
552}
553
554#[cfg(feature = "parser")]
555#[derive(Clone, PartialEq, Eq)]
556pub enum AlignItemsParseError<'a> {
557 InvalidValue(&'a str),
558}
559
560#[cfg(feature = "parser")]
561impl_debug_as_display!(AlignItemsParseError<'a>);
562#[cfg(feature = "parser")]
563impl_display! { AlignItemsParseError<'a>, {
564 InvalidValue(s) => format!("Invalid align-items value: \"{}\"", s),
565}}
566
567#[cfg(feature = "parser")]
568#[derive(Debug, Clone, PartialEq, Eq)]
569#[repr(C, u8)]
570pub enum AlignItemsParseErrorOwned {
571 InvalidValue(AzString),
572}
573
574#[cfg(feature = "parser")]
575impl AlignItemsParseError<'_> {
576 #[must_use] pub fn to_contained(&self) -> AlignItemsParseErrorOwned {
577 match self {
578 Self::InvalidValue(s) => AlignItemsParseErrorOwned::InvalidValue((*s).to_string().into()),
579 }
580 }
581}
582
583#[cfg(feature = "parser")]
584impl AlignItemsParseErrorOwned {
585 #[must_use] pub fn to_shared(&self) -> AlignItemsParseError<'_> {
586 match self {
587 Self::InvalidValue(s) => AlignItemsParseError::InvalidValue(s.as_str()),
588 }
589 }
590}
591
592#[cfg(feature = "parser")]
593pub fn parse_layout_align_items(
597 input: &str,
598) -> Result<LayoutAlignItems, AlignItemsParseError<'_>> {
599 match input.trim() {
600 "stretch" => Ok(LayoutAlignItems::Stretch),
601 "center" => Ok(LayoutAlignItems::Center),
602 "start" | "flex-start" => Ok(LayoutAlignItems::Start),
603 "end" | "flex-end" => Ok(LayoutAlignItems::End),
604 "baseline" => Ok(LayoutAlignItems::Baseline),
605 _ => Err(AlignItemsParseError::InvalidValue(input)),
606 }
607}
608
609#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
615#[repr(C)]
616#[derive(Default)]
617pub enum LayoutAlignContent {
618 #[default]
619 Stretch,
620 Center,
621 Start,
622 End,
623 SpaceBetween,
624 SpaceAround,
625}
626
627
628impl PrintAsCssValue for LayoutAlignContent {
629 fn print_as_css_value(&self) -> String {
630 String::from(match self {
631 Self::Stretch => "stretch",
632 Self::Center => "center",
633 Self::Start => "flex-start",
634 Self::End => "flex-end",
635 Self::SpaceBetween => "space-between",
636 Self::SpaceAround => "space-around",
637 })
638 }
639}
640
641#[cfg(feature = "parser")]
642#[derive(Clone, PartialEq, Eq)]
643pub enum AlignContentParseError<'a> {
644 InvalidValue(&'a str),
645}
646
647#[cfg(feature = "parser")]
648impl_debug_as_display!(AlignContentParseError<'a>);
649#[cfg(feature = "parser")]
650impl_display! { AlignContentParseError<'a>, {
651 InvalidValue(s) => format!("Invalid align-content value: \"{}\"", s),
652}}
653
654#[cfg(feature = "parser")]
655#[derive(Debug, Clone, PartialEq, Eq)]
656#[repr(C, u8)]
657pub enum AlignContentParseErrorOwned {
658 InvalidValue(AzString),
659}
660
661#[cfg(feature = "parser")]
662impl AlignContentParseError<'_> {
663 #[must_use] pub fn to_contained(&self) -> AlignContentParseErrorOwned {
664 match self {
665 Self::InvalidValue(s) => AlignContentParseErrorOwned::InvalidValue((*s).to_string().into()),
666 }
667 }
668}
669
670#[cfg(feature = "parser")]
671impl AlignContentParseErrorOwned {
672 #[must_use] pub fn to_shared(&self) -> AlignContentParseError<'_> {
673 match self {
674 Self::InvalidValue(s) => AlignContentParseError::InvalidValue(s.as_str()),
675 }
676 }
677}
678
679#[cfg(feature = "parser")]
680pub fn parse_layout_align_content(
684 input: &str,
685) -> Result<LayoutAlignContent, AlignContentParseError<'_>> {
686 match input.trim() {
687 "stretch" => Ok(LayoutAlignContent::Stretch),
688 "center" => Ok(LayoutAlignContent::Center),
689 "start" | "flex-start" => Ok(LayoutAlignContent::Start),
690 "end" | "flex-end" => Ok(LayoutAlignContent::End),
691 "space-between" => Ok(LayoutAlignContent::SpaceBetween),
692 "space-around" => Ok(LayoutAlignContent::SpaceAround),
693 _ => Err(AlignContentParseError::InvalidValue(input)),
694 }
695}
696
697#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
703#[repr(C)]
704#[derive(Default)]
705pub enum LayoutAlignSelf {
706 #[default]
707 Auto,
708 Stretch,
709 Center,
710 Start,
711 End,
712 Baseline,
713}
714
715
716impl PrintAsCssValue for LayoutAlignSelf {
717 fn print_as_css_value(&self) -> String {
718 String::from(match self {
719 Self::Auto => "auto",
720 Self::Stretch => "stretch",
721 Self::Center => "center",
722 Self::Start => "flex-start",
723 Self::End => "flex-end",
724 Self::Baseline => "baseline",
725 })
726 }
727}
728
729impl FormatAsRustCode for LayoutAlignSelf {
730 fn format_as_rust_code(&self, _tabs: usize) -> String {
731 format!(
732 "LayoutAlignSelf::{}",
733 match self {
734 Self::Auto => "Auto",
735 Self::Stretch => "Stretch",
736 Self::Center => "Center",
737 Self::Start => "Start",
738 Self::End => "End",
739 Self::Baseline => "Baseline",
740 }
741 )
742 }
743}
744
745#[cfg(feature = "parser")]
746#[derive(Clone, PartialEq, Eq)]
747pub enum AlignSelfParseError<'a> {
748 InvalidValue(&'a str),
749}
750
751#[cfg(feature = "parser")]
752impl_debug_as_display!(AlignSelfParseError<'a>);
753#[cfg(feature = "parser")]
754impl_display! { AlignSelfParseError<'a>, {
755 InvalidValue(s) => format!("Invalid align-self value: \"{}\"", s),
756}}
757
758#[cfg(feature = "parser")]
759#[derive(Debug, Clone, PartialEq, Eq)]
760#[repr(C, u8)]
761pub enum AlignSelfParseErrorOwned {
762 InvalidValue(AzString),
763}
764
765#[cfg(feature = "parser")]
766impl AlignSelfParseError<'_> {
767 #[must_use] pub fn to_contained(&self) -> AlignSelfParseErrorOwned {
768 match self {
769 Self::InvalidValue(s) => AlignSelfParseErrorOwned::InvalidValue((*s).to_string().into()),
770 }
771 }
772}
773
774#[cfg(feature = "parser")]
775impl AlignSelfParseErrorOwned {
776 #[must_use] pub fn to_shared(&self) -> AlignSelfParseError<'_> {
777 match self {
778 Self::InvalidValue(s) => AlignSelfParseError::InvalidValue(s.as_str()),
779 }
780 }
781}
782
783#[cfg(feature = "parser")]
784pub fn parse_layout_align_self(
788 input: &str,
789) -> Result<LayoutAlignSelf, AlignSelfParseError<'_>> {
790 match input.trim() {
791 "auto" => Ok(LayoutAlignSelf::Auto),
792 "stretch" => Ok(LayoutAlignSelf::Stretch),
793 "center" => Ok(LayoutAlignSelf::Center),
794 "start" | "flex-start" => Ok(LayoutAlignSelf::Start),
795 "end" | "flex-end" => Ok(LayoutAlignSelf::End),
796 "baseline" => Ok(LayoutAlignSelf::Baseline),
797 _ => Err(AlignSelfParseError::InvalidValue(input)),
798 }
799}
800
801#[allow(variant_size_differences)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
805#[repr(C, u8)]
806#[derive(Default)]
807pub enum LayoutFlexBasis {
808 #[default]
810 Auto,
811 Exact(crate::props::basic::pixel::PixelValue),
813}
814
815impl core::fmt::Debug for LayoutFlexBasis {
816 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
817 write!(f, "{}", self.print_as_css_value())
818 }
819}
820
821
822impl PrintAsCssValue for LayoutFlexBasis {
823 fn print_as_css_value(&self) -> String {
824 match self {
825 Self::Auto => "auto".to_string(),
826 Self::Exact(px) => px.print_as_css_value(),
827 }
828 }
829}
830
831impl FormatAsRustCode for LayoutFlexBasis {
832 fn format_as_rust_code(&self, _tabs: usize) -> String {
833 match self {
834 Self::Auto => String::from("LayoutFlexBasis::Auto"),
835 Self::Exact(px) => {
836 format!(
837 "LayoutFlexBasis::Exact({})",
838 crate::codegen::format::format_pixel_value(px)
839 )
840 }
841 }
842 }
843}
844
845#[cfg(feature = "parser")]
846#[derive(Clone, PartialEq, Eq)]
847pub enum FlexBasisParseError<'a> {
848 InvalidValue(&'a str),
849}
850
851#[cfg(feature = "parser")]
852impl_debug_as_display!(FlexBasisParseError<'a>);
853#[cfg(feature = "parser")]
854impl_display! { FlexBasisParseError<'a>, {
855 InvalidValue(e) => format!("Invalid flex-basis value: \"{}\"", e),
856}}
857
858#[cfg(feature = "parser")]
859#[derive(Debug, Clone, PartialEq, Eq)]
860#[repr(C, u8)]
861pub enum FlexBasisParseErrorOwned {
862 InvalidValue(AzString),
863}
864
865#[cfg(feature = "parser")]
866impl FlexBasisParseError<'_> {
867 #[must_use] pub fn to_contained(&self) -> FlexBasisParseErrorOwned {
868 match self {
869 FlexBasisParseError::InvalidValue(s) => {
870 FlexBasisParseErrorOwned::InvalidValue((*s).to_string().into())
871 }
872 }
873 }
874}
875
876#[cfg(feature = "parser")]
877impl FlexBasisParseErrorOwned {
878 #[must_use] pub fn to_shared(&self) -> FlexBasisParseError<'_> {
879 match self {
880 Self::InvalidValue(s) => {
881 FlexBasisParseError::InvalidValue(s.as_str())
882 }
883 }
884 }
885}
886
887#[cfg(feature = "parser")]
888pub fn parse_layout_flex_basis(
892 input: &str,
893) -> Result<LayoutFlexBasis, FlexBasisParseError<'_>> {
894 use crate::props::basic::pixel::parse_pixel_value;
895
896 match input.trim() {
897 "auto" => Ok(LayoutFlexBasis::Auto),
898 s => parse_pixel_value(s)
899 .map(LayoutFlexBasis::Exact)
900 .map_err(|_| FlexBasisParseError::InvalidValue(input)),
901 }
902}
903
904#[cfg(all(test, feature = "parser"))]
905mod tests {
906 #![allow(clippy::float_cmp)]
908 use super::*;
909 use crate::props::basic::pixel::PixelValue;
910
911 #[test]
912 fn test_parse_layout_flex_grow() {
913 assert_eq!(parse_layout_flex_grow("0").unwrap().inner.get(), 0.0);
914 assert_eq!(parse_layout_flex_grow("1").unwrap().inner.get(), 1.0);
915 assert_eq!(parse_layout_flex_grow("2.5").unwrap().inner.get(), 2.5);
916 assert_eq!(parse_layout_flex_grow(" 0.5 ").unwrap().inner.get(), 0.5);
917 assert!(parse_layout_flex_grow("none").is_err());
918 assert!(parse_layout_flex_grow("-1").is_err()); }
920
921 #[test]
922 fn test_parse_layout_flex_shrink() {
923 assert_eq!(parse_layout_flex_shrink("0").unwrap().inner.get(), 0.0);
924 assert_eq!(parse_layout_flex_shrink("1").unwrap().inner.get(), 1.0);
925 assert_eq!(parse_layout_flex_shrink("3.0").unwrap().inner.get(), 3.0);
926 assert_eq!(parse_layout_flex_shrink(" 0.2 ").unwrap().inner.get(), 0.2);
927 assert!(parse_layout_flex_shrink("auto").is_err());
928 assert!(parse_layout_flex_shrink("-1").is_err()); }
930
931 #[test]
932 fn test_parse_layout_flex_direction() {
933 assert_eq!(
934 parse_layout_flex_direction("row").unwrap(),
935 LayoutFlexDirection::Row
936 );
937 assert_eq!(
938 parse_layout_flex_direction("row-reverse").unwrap(),
939 LayoutFlexDirection::RowReverse
940 );
941 assert_eq!(
942 parse_layout_flex_direction("column").unwrap(),
943 LayoutFlexDirection::Column
944 );
945 assert_eq!(
946 parse_layout_flex_direction("column-reverse").unwrap(),
947 LayoutFlexDirection::ColumnReverse
948 );
949 assert_eq!(
950 parse_layout_flex_direction(" row ").unwrap(),
951 LayoutFlexDirection::Row
952 );
953 assert!(parse_layout_flex_direction("reversed-row").is_err());
954 }
955
956 #[test]
957 fn test_parse_layout_flex_wrap() {
958 assert_eq!(
959 parse_layout_flex_wrap("nowrap").unwrap(),
960 LayoutFlexWrap::NoWrap
961 );
962 assert_eq!(
963 parse_layout_flex_wrap("wrap").unwrap(),
964 LayoutFlexWrap::Wrap
965 );
966 assert_eq!(
967 parse_layout_flex_wrap("wrap-reverse").unwrap(),
968 LayoutFlexWrap::WrapReverse
969 );
970 assert_eq!(
971 parse_layout_flex_wrap(" wrap ").unwrap(),
972 LayoutFlexWrap::Wrap
973 );
974 assert!(parse_layout_flex_wrap("wrap reverse").is_err());
975 }
976
977 #[test]
978 fn test_parse_layout_justify_content() {
979 assert_eq!(
980 parse_layout_justify_content("flex-start").unwrap(),
981 LayoutJustifyContent::FlexStart
982 );
983 assert_eq!(
984 parse_layout_justify_content("flex-end").unwrap(),
985 LayoutJustifyContent::FlexEnd
986 );
987 assert_eq!(
988 parse_layout_justify_content("start").unwrap(),
989 LayoutJustifyContent::Start
990 );
991 assert_eq!(
992 parse_layout_justify_content("end").unwrap(),
993 LayoutJustifyContent::End
994 );
995 assert_eq!(
996 parse_layout_justify_content("center").unwrap(),
997 LayoutJustifyContent::Center
998 );
999 assert_eq!(
1000 parse_layout_justify_content("space-between").unwrap(),
1001 LayoutJustifyContent::SpaceBetween
1002 );
1003 assert_eq!(
1004 parse_layout_justify_content("space-around").unwrap(),
1005 LayoutJustifyContent::SpaceAround
1006 );
1007 assert_eq!(
1008 parse_layout_justify_content("space-evenly").unwrap(),
1009 LayoutJustifyContent::SpaceEvenly
1010 );
1011 assert_eq!(
1012 parse_layout_justify_content(" center ").unwrap(),
1013 LayoutJustifyContent::Center
1014 );
1015 }
1016
1017 #[test]
1018 fn test_parse_layout_align_items() {
1019 assert_eq!(
1020 parse_layout_align_items("stretch").unwrap(),
1021 LayoutAlignItems::Stretch
1022 );
1023 assert_eq!(
1024 parse_layout_align_items("flex-start").unwrap(),
1025 LayoutAlignItems::Start
1026 );
1027 assert_eq!(
1028 parse_layout_align_items("flex-end").unwrap(),
1029 LayoutAlignItems::End
1030 );
1031 assert_eq!(
1032 parse_layout_align_items("start").unwrap(),
1033 LayoutAlignItems::Start
1034 );
1035 assert_eq!(
1036 parse_layout_align_items("end").unwrap(),
1037 LayoutAlignItems::End
1038 );
1039 assert_eq!(
1040 parse_layout_align_items("center").unwrap(),
1041 LayoutAlignItems::Center
1042 );
1043 assert_eq!(
1044 parse_layout_align_items("baseline").unwrap(),
1045 LayoutAlignItems::Baseline
1046 );
1047 assert!(parse_layout_align_items("invalid").is_err());
1048 }
1049
1050 #[test]
1051 fn test_parse_layout_align_content() {
1052 assert_eq!(
1053 parse_layout_align_content("stretch").unwrap(),
1054 LayoutAlignContent::Stretch
1055 );
1056 assert_eq!(
1057 parse_layout_align_content("flex-start").unwrap(),
1058 LayoutAlignContent::Start
1059 );
1060 assert_eq!(
1061 parse_layout_align_content("flex-end").unwrap(),
1062 LayoutAlignContent::End
1063 );
1064 assert_eq!(
1065 parse_layout_align_content("center").unwrap(),
1066 LayoutAlignContent::Center
1067 );
1068 assert_eq!(
1069 parse_layout_align_content("space-between").unwrap(),
1070 LayoutAlignContent::SpaceBetween
1071 );
1072 assert_eq!(
1073 parse_layout_align_content("space-around").unwrap(),
1074 LayoutAlignContent::SpaceAround
1075 );
1076 assert!(parse_layout_align_content("space-evenly").is_err()); }
1078
1079 #[test]
1080 fn test_parse_layout_flex_basis() {
1081 assert_eq!(
1082 parse_layout_flex_basis("auto").unwrap(),
1083 LayoutFlexBasis::Auto
1084 );
1085 assert_eq!(
1086 parse_layout_flex_basis("200px").unwrap(),
1087 LayoutFlexBasis::Exact(PixelValue::px(200.0))
1088 );
1089 assert_eq!(
1090 parse_layout_flex_basis("50%").unwrap(),
1091 LayoutFlexBasis::Exact(PixelValue::percent(50.0))
1092 );
1093 assert_eq!(
1094 parse_layout_flex_basis(" 10em ").unwrap(),
1095 LayoutFlexBasis::Exact(PixelValue::em(10.0))
1096 );
1097 assert!(parse_layout_flex_basis("none").is_err());
1098 assert_eq!(
1100 parse_layout_flex_basis("200").unwrap(),
1101 LayoutFlexBasis::Exact(PixelValue::px(200.0))
1102 );
1103 assert_eq!(
1104 parse_layout_flex_basis("0").unwrap(),
1105 LayoutFlexBasis::Exact(PixelValue::px(0.0))
1106 );
1107 }
1108}