microformats_types/
class.rs1use crate::Error;
4use std::str::FromStr;
5
6#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
8#[serde(rename_all = "kebab-case")]
9pub enum KnownClass {
10 #[serde(alias = "h-entry")]
12 Entry,
13 #[serde(alias = "h-cite")]
15 Cite,
16 #[serde(alias = "h-card")]
18 Card,
19 #[serde(alias = "h-feed")]
21 Feed,
22 #[serde(alias = "h-event")]
24 Event,
25 #[serde(alias = "h-product")]
27 Product,
28 #[serde(alias = "h-adr")]
30 Adr,
31 #[serde(alias = "h-geo")]
33 Geo,
34 #[serde(alias = "h-resume")]
36 Resume,
37 #[serde(alias = "h-review")]
39 Review,
40 #[serde(alias = "h-recipe")]
42 Recipe,
43}
44
45impl FromStr for KnownClass {
46 type Err = Error;
47
48 fn from_str(s: &str) -> Result<Self, Self::Err> {
49 match s.to_ascii_lowercase().as_str() {
50 "h-entry" | "entry" => Ok(Self::Entry),
51 "h-cite" | "cite" => Ok(Self::Cite),
52 "h-card" | "card" => Ok(Self::Card),
53 "h-event" | "event" => Ok(Self::Event),
54 "h-product" | "product" => Ok(Self::Product),
55 "h-feed" | "feed" => Ok(Self::Feed),
56 "h-geo" | "geo" => Ok(Self::Geo),
57 "h-adr" | "adr" => Ok(Self::Adr),
58 "h-resume" | "resume" => Ok(Self::Resume),
59 "h-review" | "review" => Ok(Self::Review),
60 "h-recipe" | "recipe" => Ok(Self::Recipe),
61 _ => Err(Error::NotKnownClass(s.to_string())),
62 }
63 }
64}
65
66impl std::fmt::Display for KnownClass {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 f.write_str(match self {
69 KnownClass::Entry => "h-entry",
70 KnownClass::Cite => "h-cite",
71 KnownClass::Card => "h-card",
72 KnownClass::Feed => "h-feed",
73 KnownClass::Event => "h-event",
74 KnownClass::Product => "h-product",
75 KnownClass::Adr => "h-adr",
76 KnownClass::Geo => "h-geo",
77 KnownClass::Resume => "h-resume",
78 KnownClass::Review => "h-review",
79 KnownClass::Recipe => "h-recipe",
80 })
81 }
82}
83
84#[derive(Debug, Clone, Eq)]
86pub enum Class {
87 Known(KnownClass),
89 Custom(String),
91}
92
93impl PartialOrd for Class {
94 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
95 self.to_string().partial_cmp(&other.to_string())
96 }
97}
98
99impl PartialEq for Class {
100 fn eq(&self, other: &Self) -> bool {
101 self.to_string().eq(&other.to_string())
102 }
103}
104
105impl FromStr for Class {
106 type Err = std::convert::Infallible;
107
108 fn from_str(class_str: &str) -> Result<Self, Self::Err> {
109 KnownClass::from_str(class_str)
110 .or_else(|_| KnownClass::from_str(&class_str.replace("h-", "")))
111 .map(Class::Known)
112 .or_else(|_| Ok(Self::Custom(class_str.trim_start_matches("h-").to_string())))
113 }
114}
115
116impl std::fmt::Display for Class {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 match self {
119 Self::Known(class) => f.write_fmt(format_args!("{}", class)),
120 Self::Custom(class) => f.write_fmt(format_args!("h-{}", class)),
121 }
122 }
123}
124
125impl serde::Serialize for Class {
126 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
127 where
128 S: serde::Serializer,
129 {
130 serializer.serialize_str(self.to_string().as_str())
131 }
132}
133
134struct ClassVisitor;
135
136impl serde::de::Visitor<'_> for ClassVisitor {
137 type Value = Class;
138
139 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140 formatter.write_str(
141 "a string that follows Microformats class conventions of being prefixed by 'h-'",
142 )
143 }
144
145 fn visit_str<E>(self, class_str: &str) -> Result<Self::Value, E>
146 where
147 E: serde::de::Error,
148 {
149 Class::from_str(class_str).map_err(|e| E::custom(e.to_string()))
150 }
151}
152
153impl<'de> serde::Deserialize<'de> for Class {
154 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
155 where
156 D: serde::Deserializer<'de>,
157 {
158 deserializer.deserialize_string(ClassVisitor)
159 }
160}
161
162impl Class {
163 pub fn is_recognized(&self) -> bool {
165 !matches!(self, Self::Custom(_))
166 }
167}
168
169impl From<KnownClass> for Class {
170 fn from(kc: KnownClass) -> Self {
171 Self::Known(kc)
172 }
173}