uptrakit_web_api_types/
registration.rs1use serde::{Deserialize, Serialize};
2use std::str::FromStr;
3use thiserror::Error;
4
5#[non_exhaustive]
7#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
8#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
9#[cfg_attr(test, derive(strum::EnumIter))]
10#[serde(rename_all = "snake_case")]
11pub enum RegistrationMode {
12 Open,
14 Invite,
16 Closed,
18}
19
20impl RegistrationMode {
21 pub fn as_str(&self) -> &'static str {
22 match self {
23 Self::Open => "open",
24 Self::Invite => "invite",
25 Self::Closed => "closed",
26 }
27 }
28}
29
30impl std::fmt::Display for RegistrationMode {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 f.write_str(self.as_str())
33 }
34}
35
36#[derive(Debug, Error)]
37#[error("invalid registration mode value")]
38pub struct ParseRegistrationModeError;
39
40impl FromStr for RegistrationMode {
41 type Err = ParseRegistrationModeError;
42
43 fn from_str(s: &str) -> Result<Self, Self::Err> {
44 match s {
45 "open" => Ok(Self::Open),
46 "invite" => Ok(Self::Invite),
47 "closed" => Ok(Self::Closed),
48 _ => Err(ParseRegistrationModeError),
49 }
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use strum::IntoEnumIterator;
57
58 #[test]
61 fn serde_round_trip_all_variants() {
62 for mode in RegistrationMode::iter() {
63 let json = serde_json::to_string(&mode).expect("serialization should succeed");
64 let deserialized: RegistrationMode =
65 serde_json::from_str(&json).expect("deserialization should succeed");
66 assert_eq!(deserialized, mode);
67 }
68 }
69
70 #[test]
71 fn serde_serializes_as_snake_case_strings() {
72 assert_eq!(
73 serde_json::to_string(&RegistrationMode::Open).expect("serialization should succeed"),
74 r#""open""#
75 );
76 assert_eq!(
77 serde_json::to_string(&RegistrationMode::Invite).expect("serialization should succeed"),
78 r#""invite""#
79 );
80 assert_eq!(
81 serde_json::to_string(&RegistrationMode::Closed).expect("serialization should succeed"),
82 r#""closed""#
83 );
84 }
85
86 #[test]
87 fn serde_rejects_unknown_variant() {
88 let result = serde_json::from_str::<RegistrationMode>(r#""disabled""#);
89 assert!(result.is_err());
90 }
91
92 #[test]
93 fn serde_rejects_uppercase_variant() {
94 let result = serde_json::from_str::<RegistrationMode>(r#""Open""#);
95 assert!(result.is_err());
96 }
97
98 #[test]
101 fn display_open() {
102 assert_eq!(format!("{}", RegistrationMode::Open), "open");
103 }
104
105 #[test]
106 fn display_invite() {
107 assert_eq!(format!("{}", RegistrationMode::Invite), "invite");
108 }
109
110 #[test]
111 fn display_closed() {
112 assert_eq!(format!("{}", RegistrationMode::Closed), "closed");
113 }
114
115 #[test]
116 fn display_matches_as_str_for_all_variants() {
117 for mode in RegistrationMode::iter() {
118 assert_eq!(format!("{mode}"), mode.as_str());
119 }
120 }
121
122 #[test]
125 fn from_str_open() {
126 let parsed: RegistrationMode = "open".parse().expect("should parse 'open'");
127 assert_eq!(parsed, RegistrationMode::Open);
128 }
129
130 #[test]
131 fn from_str_invite() {
132 let parsed: RegistrationMode = "invite".parse().expect("should parse 'invite'");
133 assert_eq!(parsed, RegistrationMode::Invite);
134 }
135
136 #[test]
137 fn from_str_closed() {
138 let parsed: RegistrationMode = "closed".parse().expect("should parse 'closed'");
139 assert_eq!(parsed, RegistrationMode::Closed);
140 }
141
142 #[test]
143 fn from_str_round_trips_through_as_str() {
144 for mode in RegistrationMode::iter() {
145 let s = mode.as_str();
146 let parsed: RegistrationMode = s
147 .parse()
148 .expect("from_str should succeed for as_str output");
149 assert_eq!(parsed, mode);
150 }
151 }
152
153 #[test]
156 fn from_str_empty_string_fails() {
157 assert!("".parse::<RegistrationMode>().is_err());
158 }
159
160 #[test]
161 fn from_str_uppercase_fails() {
162 assert!("OPEN".parse::<RegistrationMode>().is_err());
163 assert!("Open".parse::<RegistrationMode>().is_err());
164 }
165
166 #[test]
167 fn from_str_unknown_value_fails() {
168 assert!("disabled".parse::<RegistrationMode>().is_err());
169 assert!("public".parse::<RegistrationMode>().is_err());
170 }
171
172 #[test]
173 fn from_str_whitespace_fails() {
174 assert!(" open".parse::<RegistrationMode>().is_err());
175 assert!("open ".parse::<RegistrationMode>().is_err());
176 }
177
178 #[test]
181 fn parse_error_display_message() {
182 let err = ParseRegistrationModeError;
183 assert_eq!(err.to_string(), "invalid registration mode value");
184 }
185}