1#[cfg(feature = "parse")]
12use crate::util::parse::{CssParseResult, FromCss, Parser, Token};
13
14#[derive(Copy, Clone, PartialEq, Eq, Debug)]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21#[repr(u8)]
22pub enum AlignItemsKeyword {
23 Start,
25 End,
27 FlexStart,
32 FlexEnd,
37 Center,
39 Baseline,
41 Stretch,
43}
44
45#[derive(Copy, Clone, PartialEq, Eq, Debug)]
50#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
51#[repr(u8)]
52pub enum AlignContentKeyword {
53 Start,
55 End,
57 FlexStart,
59 FlexEnd,
61 Center,
63 Stretch,
65 SpaceBetween,
68 SpaceEvenly,
71 SpaceAround,
74}
75
76impl AlignContentKeyword {
77 pub(crate) fn reversed(self) -> Self {
83 match self {
84 Self::Start => Self::End,
85 Self::End => Self::Start,
86 Self::FlexStart => Self::FlexEnd,
87 Self::FlexEnd => Self::FlexStart,
88 Self::Stretch => Self::End,
89 Self::Center | Self::SpaceBetween | Self::SpaceEvenly | Self::SpaceAround => self,
90 }
91 }
92}
93
94#[derive(Copy, Clone, PartialEq, Eq, Debug)]
109#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
110#[repr(u8)]
111pub enum AlignmentSafety {
112 Unsafe,
115 Safe,
118}
119
120#[derive(Copy, Clone, PartialEq, Eq, Debug)]
126pub struct AlignItems {
127 pub keyword: AlignItemsKeyword,
129 pub safety: AlignmentSafety,
131}
132
133impl AlignItems {
134 pub const START: Self = Self { keyword: AlignItemsKeyword::Start, safety: AlignmentSafety::Unsafe };
136 pub const END: Self = Self { keyword: AlignItemsKeyword::End, safety: AlignmentSafety::Unsafe };
138 pub const FLEX_START: Self = Self { keyword: AlignItemsKeyword::FlexStart, safety: AlignmentSafety::Unsafe };
140 pub const FLEX_END: Self = Self { keyword: AlignItemsKeyword::FlexEnd, safety: AlignmentSafety::Unsafe };
142 pub const CENTER: Self = Self { keyword: AlignItemsKeyword::Center, safety: AlignmentSafety::Unsafe };
144 pub const BASELINE: Self = Self { keyword: AlignItemsKeyword::Baseline, safety: AlignmentSafety::Unsafe };
146 pub const STRETCH: Self = Self { keyword: AlignItemsKeyword::Stretch, safety: AlignmentSafety::Unsafe };
148 pub const SAFE_START: Self = Self { keyword: AlignItemsKeyword::Start, safety: AlignmentSafety::Safe };
151 pub const SAFE_END: Self = Self { keyword: AlignItemsKeyword::End, safety: AlignmentSafety::Safe };
154 pub const SAFE_FLEX_START: Self = Self { keyword: AlignItemsKeyword::FlexStart, safety: AlignmentSafety::Safe };
157 pub const SAFE_FLEX_END: Self = Self { keyword: AlignItemsKeyword::FlexEnd, safety: AlignmentSafety::Safe };
160 pub const SAFE_CENTER: Self = Self { keyword: AlignItemsKeyword::Center, safety: AlignmentSafety::Safe };
163
164 #[inline]
166 pub const fn is_safe(self) -> bool {
167 matches!(self.safety, AlignmentSafety::Safe)
168 }
169
170 #[inline]
172 pub const fn keyword(self) -> AlignItemsKeyword {
173 self.keyword
174 }
175}
176
177#[cfg(feature = "parse")]
178impl FromCss for AlignItems {
179 fn from_css<'i>(input: &mut Parser<'i, '_>) -> CssParseResult<'i, Self> {
180 let first = input.expect_ident()?.clone();
181 cssparser::match_ignore_ascii_case! { &*first,
182 "safe" => {
183 let pos = input.expect_ident()?.clone();
184 cssparser::match_ignore_ascii_case! { &*pos,
185 "start" => Ok(Self::SAFE_START),
186 "end" => Ok(Self::SAFE_END),
187 "flex-start" => Ok(Self::SAFE_FLEX_START),
188 "flex-end" => Ok(Self::SAFE_FLEX_END),
189 "center" => Ok(Self::SAFE_CENTER),
190 _ => Err(input.new_unexpected_token_error(Token::Ident(pos))),
191 }
192 },
193 "unsafe" => {
194 let pos = input.expect_ident()?.clone();
195 cssparser::match_ignore_ascii_case! { &*pos,
196 "start" => Ok(Self::START),
197 "end" => Ok(Self::END),
198 "flex-start" => Ok(Self::FLEX_START),
199 "flex-end" => Ok(Self::FLEX_END),
200 "center" => Ok(Self::CENTER),
201 _ => Err(input.new_unexpected_token_error(Token::Ident(pos))),
202 }
203 },
204 "start" => Ok(Self::START),
205 "end" => Ok(Self::END),
206 "flex-start" => Ok(Self::FLEX_START),
207 "flex-end" => Ok(Self::FLEX_END),
208 "center" => Ok(Self::CENTER),
209 "baseline" => Ok(Self::BASELINE),
210 "stretch" => Ok(Self::STRETCH),
211 _ => Err(input.new_unexpected_token_error(Token::Ident(first))),
212 }
213 }
214}
215
216#[cfg(feature = "parse")]
217crate::util::parse::from_str_from_css!(AlignItems);
218
219pub type JustifyItems = AlignItems;
225pub type AlignSelf = AlignItems;
233pub type JustifySelf = AlignItems;
241
242#[derive(Copy, Clone, PartialEq, Eq, Debug)]
248pub struct AlignContent {
249 pub keyword: AlignContentKeyword,
251 pub safety: AlignmentSafety,
253}
254
255impl AlignContent {
256 pub const START: Self = Self { keyword: AlignContentKeyword::Start, safety: AlignmentSafety::Unsafe };
258 pub const END: Self = Self { keyword: AlignContentKeyword::End, safety: AlignmentSafety::Unsafe };
260 pub const FLEX_START: Self = Self { keyword: AlignContentKeyword::FlexStart, safety: AlignmentSafety::Unsafe };
262 pub const FLEX_END: Self = Self { keyword: AlignContentKeyword::FlexEnd, safety: AlignmentSafety::Unsafe };
264 pub const CENTER: Self = Self { keyword: AlignContentKeyword::Center, safety: AlignmentSafety::Unsafe };
266 pub const STRETCH: Self = Self { keyword: AlignContentKeyword::Stretch, safety: AlignmentSafety::Unsafe };
268 pub const SPACE_BETWEEN: Self =
270 Self { keyword: AlignContentKeyword::SpaceBetween, safety: AlignmentSafety::Unsafe };
271 pub const SPACE_EVENLY: Self = Self { keyword: AlignContentKeyword::SpaceEvenly, safety: AlignmentSafety::Unsafe };
273 pub const SPACE_AROUND: Self = Self { keyword: AlignContentKeyword::SpaceAround, safety: AlignmentSafety::Unsafe };
275 pub const SAFE_START: Self = Self { keyword: AlignContentKeyword::Start, safety: AlignmentSafety::Safe };
278 pub const SAFE_END: Self = Self { keyword: AlignContentKeyword::End, safety: AlignmentSafety::Safe };
281 pub const SAFE_FLEX_START: Self = Self { keyword: AlignContentKeyword::FlexStart, safety: AlignmentSafety::Safe };
284 pub const SAFE_FLEX_END: Self = Self { keyword: AlignContentKeyword::FlexEnd, safety: AlignmentSafety::Safe };
287 pub const SAFE_CENTER: Self = Self { keyword: AlignContentKeyword::Center, safety: AlignmentSafety::Safe };
290
291 #[inline]
293 pub const fn is_safe(self) -> bool {
294 matches!(self.safety, AlignmentSafety::Safe)
295 }
296
297 #[inline]
299 pub const fn keyword(self) -> AlignContentKeyword {
300 self.keyword
301 }
302}
303
304#[cfg(feature = "parse")]
305impl FromCss for AlignContent {
306 fn from_css<'i>(input: &mut Parser<'i, '_>) -> CssParseResult<'i, Self> {
307 let first = input.expect_ident()?.clone();
308 cssparser::match_ignore_ascii_case! { &*first,
309 "safe" => {
310 let pos = input.expect_ident()?.clone();
311 cssparser::match_ignore_ascii_case! { &*pos,
312 "start" => Ok(Self::SAFE_START),
313 "end" => Ok(Self::SAFE_END),
314 "flex-start" => Ok(Self::SAFE_FLEX_START),
315 "flex-end" => Ok(Self::SAFE_FLEX_END),
316 "center" => Ok(Self::SAFE_CENTER),
317 _ => Err(input.new_unexpected_token_error(Token::Ident(pos))),
318 }
319 },
320 "unsafe" => {
321 let pos = input.expect_ident()?.clone();
322 cssparser::match_ignore_ascii_case! { &*pos,
323 "start" => Ok(Self::START),
324 "end" => Ok(Self::END),
325 "flex-start" => Ok(Self::FLEX_START),
326 "flex-end" => Ok(Self::FLEX_END),
327 "center" => Ok(Self::CENTER),
328 _ => Err(input.new_unexpected_token_error(Token::Ident(pos))),
329 }
330 },
331 "start" => Ok(Self::START),
332 "end" => Ok(Self::END),
333 "flex-start" => Ok(Self::FLEX_START),
334 "flex-end" => Ok(Self::FLEX_END),
335 "center" => Ok(Self::CENTER),
336 "stretch" => Ok(Self::STRETCH),
337 "space-between" => Ok(Self::SPACE_BETWEEN),
338 "space-evenly" => Ok(Self::SPACE_EVENLY),
339 "space-around" => Ok(Self::SPACE_AROUND),
340 _ => Err(input.new_unexpected_token_error(Token::Ident(first))),
341 }
342 }
343}
344
345#[cfg(feature = "parse")]
346crate::util::parse::from_str_from_css!(AlignContent);
347
348pub type JustifyContent = AlignContent;
354
355#[cfg(feature = "serde")]
364const ALIGN_ITEMS_NAMES: &[&str] = &[
365 "Start",
366 "End",
367 "FlexStart",
368 "FlexEnd",
369 "Center",
370 "Baseline",
371 "Stretch",
372 "SafeStart",
373 "SafeEnd",
374 "SafeFlexStart",
375 "SafeFlexEnd",
376 "SafeCenter",
377];
378
379#[cfg(feature = "serde")]
380impl serde::Serialize for AlignItems {
381 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
382 let name = match (self.keyword, self.safety) {
383 (AlignItemsKeyword::Start, AlignmentSafety::Unsafe) => "Start",
384 (AlignItemsKeyword::End, AlignmentSafety::Unsafe) => "End",
385 (AlignItemsKeyword::FlexStart, AlignmentSafety::Unsafe) => "FlexStart",
386 (AlignItemsKeyword::FlexEnd, AlignmentSafety::Unsafe) => "FlexEnd",
387 (AlignItemsKeyword::Center, AlignmentSafety::Unsafe) => "Center",
388 (AlignItemsKeyword::Baseline, _) => "Baseline",
389 (AlignItemsKeyword::Stretch, _) => "Stretch",
390 (AlignItemsKeyword::Start, AlignmentSafety::Safe) => "SafeStart",
391 (AlignItemsKeyword::End, AlignmentSafety::Safe) => "SafeEnd",
392 (AlignItemsKeyword::FlexStart, AlignmentSafety::Safe) => "SafeFlexStart",
393 (AlignItemsKeyword::FlexEnd, AlignmentSafety::Safe) => "SafeFlexEnd",
394 (AlignItemsKeyword::Center, AlignmentSafety::Safe) => "SafeCenter",
395 };
396 serializer.serialize_str(name)
397 }
398}
399
400#[cfg(feature = "serde")]
401impl<'de> serde::Deserialize<'de> for AlignItems {
402 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
403 struct AlignItemsVisitor;
404 impl<'de> serde::de::Visitor<'de> for AlignItemsVisitor {
405 type Value = AlignItems;
406 fn expecting(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
407 fmt.write_str("an AlignItems variant tag string")
408 }
409 fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
410 Ok(match v {
411 "Start" => AlignItems::START,
412 "End" => AlignItems::END,
413 "FlexStart" => AlignItems::FLEX_START,
414 "FlexEnd" => AlignItems::FLEX_END,
415 "Center" => AlignItems::CENTER,
416 "Baseline" => AlignItems::BASELINE,
417 "Stretch" => AlignItems::STRETCH,
418 "SafeStart" => AlignItems::SAFE_START,
419 "SafeEnd" => AlignItems::SAFE_END,
420 "SafeFlexStart" => AlignItems::SAFE_FLEX_START,
421 "SafeFlexEnd" => AlignItems::SAFE_FLEX_END,
422 "SafeCenter" => AlignItems::SAFE_CENTER,
423 other => return Err(E::unknown_variant(other, ALIGN_ITEMS_NAMES)),
424 })
425 }
426 }
427 deserializer.deserialize_str(AlignItemsVisitor)
428 }
429}
430
431#[cfg(feature = "serde")]
434const ALIGN_CONTENT_NAMES: &[&str] = &[
435 "Start",
436 "End",
437 "FlexStart",
438 "FlexEnd",
439 "Center",
440 "Stretch",
441 "SpaceBetween",
442 "SpaceEvenly",
443 "SpaceAround",
444 "SafeStart",
445 "SafeEnd",
446 "SafeFlexStart",
447 "SafeFlexEnd",
448 "SafeCenter",
449];
450
451#[cfg(feature = "serde")]
452impl serde::Serialize for AlignContent {
453 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
454 let name = match (self.keyword, self.safety) {
455 (AlignContentKeyword::Start, AlignmentSafety::Unsafe) => "Start",
456 (AlignContentKeyword::End, AlignmentSafety::Unsafe) => "End",
457 (AlignContentKeyword::FlexStart, AlignmentSafety::Unsafe) => "FlexStart",
458 (AlignContentKeyword::FlexEnd, AlignmentSafety::Unsafe) => "FlexEnd",
459 (AlignContentKeyword::Center, AlignmentSafety::Unsafe) => "Center",
460 (AlignContentKeyword::Stretch, _) => "Stretch",
461 (AlignContentKeyword::SpaceBetween, _) => "SpaceBetween",
462 (AlignContentKeyword::SpaceEvenly, _) => "SpaceEvenly",
463 (AlignContentKeyword::SpaceAround, _) => "SpaceAround",
464 (AlignContentKeyword::Start, AlignmentSafety::Safe) => "SafeStart",
465 (AlignContentKeyword::End, AlignmentSafety::Safe) => "SafeEnd",
466 (AlignContentKeyword::FlexStart, AlignmentSafety::Safe) => "SafeFlexStart",
467 (AlignContentKeyword::FlexEnd, AlignmentSafety::Safe) => "SafeFlexEnd",
468 (AlignContentKeyword::Center, AlignmentSafety::Safe) => "SafeCenter",
469 };
470 serializer.serialize_str(name)
471 }
472}
473
474#[cfg(feature = "serde")]
475impl<'de> serde::Deserialize<'de> for AlignContent {
476 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
477 struct AlignContentVisitor;
478 impl<'de> serde::de::Visitor<'de> for AlignContentVisitor {
479 type Value = AlignContent;
480 fn expecting(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
481 fmt.write_str("an AlignContent variant tag string")
482 }
483 fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
484 Ok(match v {
485 "Start" => AlignContent::START,
486 "End" => AlignContent::END,
487 "FlexStart" => AlignContent::FLEX_START,
488 "FlexEnd" => AlignContent::FLEX_END,
489 "Center" => AlignContent::CENTER,
490 "Stretch" => AlignContent::STRETCH,
491 "SpaceBetween" => AlignContent::SPACE_BETWEEN,
492 "SpaceEvenly" => AlignContent::SPACE_EVENLY,
493 "SpaceAround" => AlignContent::SPACE_AROUND,
494 "SafeStart" => AlignContent::SAFE_START,
495 "SafeEnd" => AlignContent::SAFE_END,
496 "SafeFlexStart" => AlignContent::SAFE_FLEX_START,
497 "SafeFlexEnd" => AlignContent::SAFE_FLEX_END,
498 "SafeCenter" => AlignContent::SAFE_CENTER,
499 other => return Err(E::unknown_variant(other, ALIGN_CONTENT_NAMES)),
500 })
501 }
502 }
503 deserializer.deserialize_str(AlignContentVisitor)
504 }
505}
506
507#[cfg(test)]
508mod tests {
509 use super::*;
510 use core::mem::size_of;
511
512 #[test]
515 fn align_types_within_size_budget() {
516 assert!(size_of::<AlignItems>() <= 2, "AlignItems grew to {}", size_of::<AlignItems>());
517 assert!(size_of::<AlignContent>() <= 2, "AlignContent grew to {}", size_of::<AlignContent>());
518 assert!(size_of::<Option<AlignItems>>() <= 3);
519 assert!(size_of::<Option<AlignContent>>() <= 3);
520 }
521
522 #[test]
523 fn align_items_is_safe() {
524 assert!(AlignItems::SAFE_START.is_safe());
525 assert!(AlignItems::SAFE_END.is_safe());
526 assert!(AlignItems::SAFE_FLEX_START.is_safe());
527 assert!(AlignItems::SAFE_FLEX_END.is_safe());
528 assert!(AlignItems::SAFE_CENTER.is_safe());
529 assert!(!AlignItems::START.is_safe());
530 assert!(!AlignItems::END.is_safe());
531 assert!(!AlignItems::FLEX_START.is_safe());
532 assert!(!AlignItems::FLEX_END.is_safe());
533 assert!(!AlignItems::CENTER.is_safe());
534 assert!(!AlignItems::BASELINE.is_safe());
535 assert!(!AlignItems::STRETCH.is_safe());
536 }
537
538 #[test]
539 fn align_items_keyword_strips_safe() {
540 assert_eq!(AlignItems::SAFE_START.keyword(), AlignItemsKeyword::Start);
541 assert_eq!(AlignItems::SAFE_END.keyword(), AlignItemsKeyword::End);
542 assert_eq!(AlignItems::SAFE_FLEX_START.keyword(), AlignItemsKeyword::FlexStart);
543 assert_eq!(AlignItems::SAFE_FLEX_END.keyword(), AlignItemsKeyword::FlexEnd);
544 assert_eq!(AlignItems::SAFE_CENTER.keyword(), AlignItemsKeyword::Center);
545 }
546
547 #[test]
548 fn align_items_keyword_passthrough() {
549 assert_eq!(AlignItems::START.keyword(), AlignItemsKeyword::Start);
550 assert_eq!(AlignItems::STRETCH.keyword(), AlignItemsKeyword::Stretch);
551 assert_eq!(AlignItems::BASELINE.keyword(), AlignItemsKeyword::Baseline);
552 assert_eq!(AlignItems::FLEX_START.keyword(), AlignItemsKeyword::FlexStart);
553 }
554
555 #[test]
556 fn align_content_is_safe() {
557 assert!(AlignContent::SAFE_START.is_safe());
558 assert!(AlignContent::SAFE_CENTER.is_safe());
559 assert!(!AlignContent::SPACE_BETWEEN.is_safe());
560 assert!(!AlignContent::STRETCH.is_safe());
561 }
562
563 #[test]
564 fn align_content_keyword_strips_safe() {
565 assert_eq!(AlignContent::SAFE_START.keyword(), AlignContentKeyword::Start);
566 assert_eq!(AlignContent::SAFE_FLEX_END.keyword(), AlignContentKeyword::FlexEnd);
567 assert_eq!(AlignContent::SAFE_CENTER.keyword(), AlignContentKeyword::Center);
568 assert_eq!(AlignContent::SPACE_BETWEEN.keyword(), AlignContentKeyword::SpaceBetween);
569 }
570
571 #[test]
572 fn align_content_keyword_reversed_swaps_start_end() {
573 assert_eq!(AlignContentKeyword::Start.reversed(), AlignContentKeyword::End);
574 assert_eq!(AlignContentKeyword::End.reversed(), AlignContentKeyword::Start);
575 assert_eq!(AlignContentKeyword::FlexStart.reversed(), AlignContentKeyword::FlexEnd);
576 assert_eq!(AlignContentKeyword::FlexEnd.reversed(), AlignContentKeyword::FlexStart);
577 assert_eq!(AlignContentKeyword::Stretch.reversed(), AlignContentKeyword::End);
579 assert_eq!(AlignContentKeyword::Center.reversed(), AlignContentKeyword::Center);
580 assert_eq!(AlignContentKeyword::SpaceBetween.reversed(), AlignContentKeyword::SpaceBetween);
581 assert_eq!(AlignContentKeyword::SpaceEvenly.reversed(), AlignContentKeyword::SpaceEvenly);
582 assert_eq!(AlignContentKeyword::SpaceAround.reversed(), AlignContentKeyword::SpaceAround);
583 }
584
585 #[cfg(feature = "parse")]
586 #[test]
587 fn parse_align_items_plain() {
588 assert_eq!("start".parse::<AlignItems>().unwrap(), AlignItems::START);
589 assert_eq!("end".parse::<AlignItems>().unwrap(), AlignItems::END);
590 assert_eq!("flex-start".parse::<AlignItems>().unwrap(), AlignItems::FLEX_START);
591 assert_eq!("flex-end".parse::<AlignItems>().unwrap(), AlignItems::FLEX_END);
592 assert_eq!("center".parse::<AlignItems>().unwrap(), AlignItems::CENTER);
593 assert_eq!("baseline".parse::<AlignItems>().unwrap(), AlignItems::BASELINE);
594 assert_eq!("stretch".parse::<AlignItems>().unwrap(), AlignItems::STRETCH);
595 }
596
597 #[cfg(feature = "parse")]
598 #[test]
599 fn parse_align_items_safe() {
600 assert_eq!("safe start".parse::<AlignItems>().unwrap(), AlignItems::SAFE_START);
601 assert_eq!("safe end".parse::<AlignItems>().unwrap(), AlignItems::SAFE_END);
602 assert_eq!("safe flex-start".parse::<AlignItems>().unwrap(), AlignItems::SAFE_FLEX_START);
603 assert_eq!("safe flex-end".parse::<AlignItems>().unwrap(), AlignItems::SAFE_FLEX_END);
604 assert_eq!("safe center".parse::<AlignItems>().unwrap(), AlignItems::SAFE_CENTER);
605 }
606
607 #[cfg(feature = "parse")]
608 #[test]
609 fn parse_align_items_safe_case_insensitive() {
610 assert_eq!("SAFE Start".parse::<AlignItems>().unwrap(), AlignItems::SAFE_START);
611 assert_eq!("Safe FLEX-end".parse::<AlignItems>().unwrap(), AlignItems::SAFE_FLEX_END);
612 }
613
614 #[cfg(feature = "parse")]
615 #[test]
616 fn parse_align_items_unsafe_drops_modifier() {
617 assert_eq!("unsafe start".parse::<AlignItems>().unwrap(), AlignItems::START);
618 assert_eq!("unsafe end".parse::<AlignItems>().unwrap(), AlignItems::END);
619 assert_eq!("unsafe center".parse::<AlignItems>().unwrap(), AlignItems::CENTER);
620 }
621
622 #[cfg(feature = "parse")]
623 #[test]
624 fn parse_align_items_rejects_invalid_safe_combos() {
625 assert!("safe stretch".parse::<AlignItems>().is_err());
626 assert!("safe baseline".parse::<AlignItems>().is_err());
627 assert!("safe space-between".parse::<AlignItems>().is_err());
628 assert!("safe".parse::<AlignItems>().is_err());
629 assert!("safe garbage".parse::<AlignItems>().is_err());
630 assert!("unsafe stretch".parse::<AlignItems>().is_err());
631 assert!("unsafe baseline".parse::<AlignItems>().is_err());
632 }
633
634 #[cfg(feature = "parse")]
635 #[test]
636 fn parse_align_content_plain() {
637 assert_eq!("start".parse::<AlignContent>().unwrap(), AlignContent::START);
638 assert_eq!("space-between".parse::<AlignContent>().unwrap(), AlignContent::SPACE_BETWEEN);
639 assert_eq!("space-evenly".parse::<AlignContent>().unwrap(), AlignContent::SPACE_EVENLY);
640 assert_eq!("space-around".parse::<AlignContent>().unwrap(), AlignContent::SPACE_AROUND);
641 assert_eq!("stretch".parse::<AlignContent>().unwrap(), AlignContent::STRETCH);
642 }
643
644 #[cfg(feature = "parse")]
645 #[test]
646 fn parse_align_content_safe() {
647 assert_eq!("safe start".parse::<AlignContent>().unwrap(), AlignContent::SAFE_START);
648 assert_eq!("safe end".parse::<AlignContent>().unwrap(), AlignContent::SAFE_END);
649 assert_eq!("safe flex-start".parse::<AlignContent>().unwrap(), AlignContent::SAFE_FLEX_START);
650 assert_eq!("safe flex-end".parse::<AlignContent>().unwrap(), AlignContent::SAFE_FLEX_END);
651 assert_eq!("safe center".parse::<AlignContent>().unwrap(), AlignContent::SAFE_CENTER);
652 }
653
654 #[cfg(feature = "parse")]
655 #[test]
656 fn parse_align_content_unsafe_drops_modifier() {
657 assert_eq!("unsafe start".parse::<AlignContent>().unwrap(), AlignContent::START);
658 assert_eq!("unsafe flex-end".parse::<AlignContent>().unwrap(), AlignContent::FLEX_END);
659 }
660
661 #[cfg(feature = "parse")]
662 #[test]
663 fn parse_align_content_rejects_invalid_safe_combos() {
664 assert!("safe stretch".parse::<AlignContent>().is_err());
665 assert!("safe space-between".parse::<AlignContent>().is_err());
666 assert!("safe space-evenly".parse::<AlignContent>().is_err());
667 assert!("safe space-around".parse::<AlignContent>().is_err());
668 assert!("safe".parse::<AlignContent>().is_err());
669 assert!("unsafe stretch".parse::<AlignContent>().is_err());
670 assert!("unsafe space-between".parse::<AlignContent>().is_err());
671 }
672
673 #[cfg(feature = "serde")]
674 #[test]
675 fn serde_align_items_round_trip() {
676 let cases = [
677 (AlignItems::START, "\"Start\""),
678 (AlignItems::END, "\"End\""),
679 (AlignItems::FLEX_START, "\"FlexStart\""),
680 (AlignItems::FLEX_END, "\"FlexEnd\""),
681 (AlignItems::CENTER, "\"Center\""),
682 (AlignItems::BASELINE, "\"Baseline\""),
683 (AlignItems::STRETCH, "\"Stretch\""),
684 (AlignItems::SAFE_START, "\"SafeStart\""),
685 (AlignItems::SAFE_END, "\"SafeEnd\""),
686 (AlignItems::SAFE_FLEX_START, "\"SafeFlexStart\""),
687 (AlignItems::SAFE_FLEX_END, "\"SafeFlexEnd\""),
688 (AlignItems::SAFE_CENTER, "\"SafeCenter\""),
689 ];
690 for (value, expected) in cases {
691 let serialized = serde_json::to_string(&value).unwrap();
692 assert_eq!(serialized, expected, "serialize {:?}", value);
693 let deserialized: AlignItems = serde_json::from_str(expected).unwrap();
694 assert_eq!(deserialized, value, "round-trip {:?}", value);
695 }
696 assert!(serde_json::from_str::<AlignItems>("\"NotAVariant\"").is_err());
697 }
698
699 #[cfg(feature = "serde")]
700 #[test]
701 fn serde_align_content_round_trip() {
702 let cases = [
703 (AlignContent::START, "\"Start\""),
704 (AlignContent::END, "\"End\""),
705 (AlignContent::FLEX_START, "\"FlexStart\""),
706 (AlignContent::FLEX_END, "\"FlexEnd\""),
707 (AlignContent::CENTER, "\"Center\""),
708 (AlignContent::STRETCH, "\"Stretch\""),
709 (AlignContent::SPACE_BETWEEN, "\"SpaceBetween\""),
710 (AlignContent::SPACE_EVENLY, "\"SpaceEvenly\""),
711 (AlignContent::SPACE_AROUND, "\"SpaceAround\""),
712 (AlignContent::SAFE_START, "\"SafeStart\""),
713 (AlignContent::SAFE_END, "\"SafeEnd\""),
714 (AlignContent::SAFE_FLEX_START, "\"SafeFlexStart\""),
715 (AlignContent::SAFE_FLEX_END, "\"SafeFlexEnd\""),
716 (AlignContent::SAFE_CENTER, "\"SafeCenter\""),
717 ];
718 for (value, expected) in cases {
719 let serialized = serde_json::to_string(&value).unwrap();
720 assert_eq!(serialized, expected, "serialize {:?}", value);
721 let deserialized: AlignContent = serde_json::from_str(expected).unwrap();
722 assert_eq!(deserialized, value, "round-trip {:?}", value);
723 }
724 assert!(serde_json::from_str::<AlignContent>("\"NotAVariant\"").is_err());
725 }
726}