1#[cfg(feature = "chumsky")]
4use chumsky::{Parser, prelude::just};
5
6#[derive(
8 Debug,
9 Clone,
10 Hash,
11 PartialEq,
12 Eq,
13 PartialOrd,
14 Ord,
15 strum::EnumIs,
16 serde::Serialize,
17 serde::Deserialize,
18)]
19#[expect(
20 clippy::module_name_repetitions,
21 reason = "the type is used outside this module"
22)]
23pub enum SearchCategory {
24 All,
26 People,
28 Places,
30 Events,
32 Groups,
34 Wiki,
36 Destinations,
38 Classifieds,
40}
41
42#[cfg(feature = "chumsky")]
48#[must_use]
49#[expect(
50 clippy::module_name_repetitions,
51 reason = "the parser is used outside this module"
52)]
53pub fn search_category_parser<'src>()
54-> impl Parser<'src, &'src str, SearchCategory, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
55{
56 just("all")
57 .to(SearchCategory::All)
58 .or(just("people").to(SearchCategory::People))
59 .or(just("places").to(SearchCategory::Places))
60 .or(just("events").to(SearchCategory::Events))
61 .or(just("groups").to(SearchCategory::Groups))
62 .or(just("wiki").to(SearchCategory::Wiki))
63 .or(just("destinations").to(SearchCategory::Destinations))
64 .or(just("classifieds").to(SearchCategory::Classifieds))
65}
66
67impl std::fmt::Display for SearchCategory {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 match self {
70 Self::All => write!(f, "all"),
71 Self::People => write!(f, "people"),
72 Self::Places => write!(f, "places"),
73 Self::Events => write!(f, "events"),
74 Self::Groups => write!(f, "groups"),
75 Self::Wiki => write!(f, "wiki"),
76 Self::Destinations => write!(f, "destinations"),
77 Self::Classifieds => write!(f, "classifieds"),
78 }
79 }
80}
81
82#[derive(Debug, Clone)]
84#[expect(
85 clippy::module_name_repetitions,
86 reason = "the type is used outside this module"
87)]
88pub struct SearchCategoryParseError {
89 value: String,
91}
92
93impl std::fmt::Display for SearchCategoryParseError {
94 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95 write!(f, "Could not parse as SearchCategory: {}", self.value)
96 }
97}
98
99impl std::str::FromStr for SearchCategory {
100 type Err = SearchCategoryParseError;
101
102 fn from_str(s: &str) -> Result<Self, Self::Err> {
103 match s {
104 "all" => Ok(Self::All),
105 "people" => Ok(Self::People),
106 "places" => Ok(Self::Places),
107 "events" => Ok(Self::Events),
108 "groups" => Ok(Self::Groups),
109 "wiki" => Ok(Self::Wiki),
110 "destinations" => Ok(Self::Destinations),
111 "classifieds" => Ok(Self::Classifieds),
112 _ => Err(SearchCategoryParseError {
113 value: s.to_owned(),
114 }),
115 }
116 }
117}
118
119#[derive(
130 Debug,
131 Clone,
132 Copy,
133 PartialEq,
134 Eq,
135 Hash,
136 PartialOrd,
137 Ord,
138 Default,
139 serde::Serialize,
140 serde::Deserialize,
141)]
142pub struct EventId(pub u32);
143
144impl EventId {
145 #[must_use]
147 pub const fn new(id: u32) -> Self {
148 Self(id)
149 }
150
151 #[must_use]
153 pub const fn get(self) -> u32 {
154 self.0
155 }
156}
157
158impl std::fmt::Display for EventId {
159 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160 write!(f, "{}", self.0)
161 }
162}
163
164#[cfg(feature = "chumsky")]
172#[must_use]
173pub fn event_id_parser<'src>()
174-> impl Parser<'src, &'src str, EventId, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
175 crate::utils::u32_parser().map(EventId)
176}
177
178#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
188#[non_exhaustive]
189pub enum ClassifiedCategory {
190 #[default]
192 AnyCategory,
193 Shopping,
195 LandRental,
197 PropertyRental,
199 SpecialAttraction,
201 NewProducts,
203 Employment,
205 Wanted,
207 Service,
209 Personal,
211 Unknown(u32),
214}
215
216impl ClassifiedCategory {
217 #[must_use]
219 pub const fn from_u32(value: u32) -> Self {
220 match value {
221 0 => Self::AnyCategory,
222 1 => Self::Shopping,
223 2 => Self::LandRental,
224 3 => Self::PropertyRental,
225 4 => Self::SpecialAttraction,
226 5 => Self::NewProducts,
227 6 => Self::Employment,
228 7 => Self::Wanted,
229 8 => Self::Service,
230 9 => Self::Personal,
231 other => Self::Unknown(other),
232 }
233 }
234
235 #[must_use]
237 pub const fn to_u32(self) -> u32 {
238 match self {
239 Self::AnyCategory => 0,
240 Self::Shopping => 1,
241 Self::LandRental => 2,
242 Self::PropertyRental => 3,
243 Self::SpecialAttraction => 4,
244 Self::NewProducts => 5,
245 Self::Employment => 6,
246 Self::Wanted => 7,
247 Self::Service => 8,
248 Self::Personal => 9,
249 Self::Unknown(value) => value,
250 }
251 }
252}
253
254impl std::fmt::Display for ClassifiedCategory {
255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256 match self {
257 Self::AnyCategory => write!(f, "any"),
258 Self::Shopping => write!(f, "shopping"),
259 Self::LandRental => write!(f, "land rental"),
260 Self::PropertyRental => write!(f, "property rental"),
261 Self::SpecialAttraction => write!(f, "special attraction"),
262 Self::NewProducts => write!(f, "new products"),
263 Self::Employment => write!(f, "employment"),
264 Self::Wanted => write!(f, "wanted"),
265 Self::Service => write!(f, "service"),
266 Self::Personal => write!(f, "personal"),
267 Self::Unknown(value) => write!(f, "{value}"),
268 }
269 }
270}
271
272impl serde::Serialize for ClassifiedCategory {
273 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
277 where
278 S: serde::Serializer,
279 {
280 serializer.serialize_u32(self.to_u32())
281 }
282}
283
284impl<'de> serde::Deserialize<'de> for ClassifiedCategory {
285 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
286 where
287 D: serde::Deserializer<'de>,
288 {
289 Ok(Self::from_u32(u32::deserialize(deserializer)?))
290 }
291}
292
293#[derive(Debug, Clone)]
295pub struct ClassifiedCategoryParseError {
296 value: String,
298}
299
300impl std::fmt::Display for ClassifiedCategoryParseError {
301 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
302 write!(f, "Could not parse as ClassifiedCategory: {}", self.value)
303 }
304}
305
306impl std::str::FromStr for ClassifiedCategory {
307 type Err = ClassifiedCategoryParseError;
308
309 fn from_str(s: &str) -> Result<Self, Self::Err> {
310 match s {
311 "any" => Ok(Self::AnyCategory),
312 "shopping" => Ok(Self::Shopping),
313 "land rental" => Ok(Self::LandRental),
314 "property rental" => Ok(Self::PropertyRental),
315 "special attraction" => Ok(Self::SpecialAttraction),
316 "new products" => Ok(Self::NewProducts),
317 "employment" => Ok(Self::Employment),
318 "wanted" => Ok(Self::Wanted),
319 "service" => Ok(Self::Service),
320 "personal" => Ok(Self::Personal),
321 _ => Err(ClassifiedCategoryParseError {
322 value: s.to_owned(),
323 }),
324 }
325 }
326}
327
328#[cfg(feature = "chumsky")]
335#[must_use]
336pub fn classified_category_parser<'src>() -> impl Parser<
337 'src,
338 &'src str,
339 ClassifiedCategory,
340 chumsky::extra::Err<chumsky::error::Rich<'src, char>>,
341> {
342 just("any")
343 .to(ClassifiedCategory::AnyCategory)
344 .or(just("shopping").to(ClassifiedCategory::Shopping))
345 .or(just("land rental").to(ClassifiedCategory::LandRental))
346 .or(just("property rental").to(ClassifiedCategory::PropertyRental))
347 .or(just("special attraction").to(ClassifiedCategory::SpecialAttraction))
348 .or(just("new products").to(ClassifiedCategory::NewProducts))
349 .or(just("employment").to(ClassifiedCategory::Employment))
350 .or(just("wanted").to(ClassifiedCategory::Wanted))
351 .or(just("service").to(ClassifiedCategory::Service))
352 .or(just("personal").to(ClassifiedCategory::Personal))
353}