1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
15pub enum FontDisplay {
16 #[default]
18 Auto,
19 Block,
22 Swap,
25 Fallback,
28 Optional,
31}
32
33impl FontDisplay {
34 #[must_use]
37 pub const fn keyword(self) -> &'static str {
38 match self {
39 Self::Auto => "auto",
40 Self::Block => "block",
41 Self::Swap => "swap",
42 Self::Fallback => "fallback",
43 Self::Optional => "optional",
44 }
45 }
46
47 #[must_use]
50 pub fn from_keyword(keyword: &str) -> Option<Self> {
51 Some(match keyword {
52 "auto" => Self::Auto,
53 "block" => Self::Block,
54 "swap" => Self::Swap,
55 "fallback" => Self::Fallback,
56 "optional" => Self::Optional,
57 _ => return None,
58 })
59 }
60
61 pub(crate) const fn hash(
63 self,
64 h: topcoat_core::fnv1a::Fnv1a<u64>,
65 ) -> topcoat_core::fnv1a::Fnv1a<u64> {
66 h.write(self.keyword().as_bytes())
67 }
68}
69
70impl std::fmt::Display for FontDisplay {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 f.write_str(self.keyword())
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn default_is_auto() {
82 assert_eq!(FontDisplay::default(), FontDisplay::Auto);
83 }
84
85 #[test]
86 fn displays_as_its_keyword() {
87 assert_eq!(FontDisplay::Auto.to_string(), "auto");
88 assert_eq!(FontDisplay::Block.to_string(), "block");
89 assert_eq!(FontDisplay::Swap.to_string(), "swap");
90 assert_eq!(FontDisplay::Fallback.to_string(), "fallback");
91 assert_eq!(FontDisplay::Optional.to_string(), "optional");
92 }
93
94 #[test]
95 fn from_keyword_round_trips() {
96 for strategy in [
97 FontDisplay::Auto,
98 FontDisplay::Block,
99 FontDisplay::Swap,
100 FontDisplay::Fallback,
101 FontDisplay::Optional,
102 ] {
103 assert_eq!(
104 FontDisplay::from_keyword(strategy.keyword()),
105 Some(strategy)
106 );
107 }
108 }
109
110 #[test]
111 fn from_keyword_rejects_unknown() {
112 assert_eq!(FontDisplay::from_keyword("infinite"), None);
113 }
114}