1use serde::{Deserialize, Serialize};
2
3pub mod api_format {
5 use serde::{Serialize, Serializer};
6
7 pub fn serialize_enum<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
9 where
10 S: Serializer,
11 T: super::ApiEnum,
12 {
13 serializer.serialize_i8(value.to_api_value())
14 }
15
16 pub fn serialize_option_enum<S, T>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
18 where
19 S: Serializer,
20 T: super::ApiEnum,
21 {
22 match value {
23 Some(v) => serializer.serialize_i8(v.to_api_value()),
24 None => serializer.serialize_none(),
25 }
26 }
27
28 pub fn serialize_vec_enum<S, T>(values: &[T], serializer: S) -> Result<S::Ok, S::Error>
30 where
31 S: Serializer,
32 T: super::ApiEnum,
33 {
34 let nums: Vec<i8> = values.iter().map(|e| e.to_api_value()).collect();
35 nums.serialize(serializer)
36 }
37}
38
39pub trait ApiEnum: Sized {
41 fn to_api_value(&self) -> i8;
42 fn from_string(s: &str) -> Option<Self>;
43}
44
45macro_rules! impl_numeric_string_enum {
47 ($enum_name:ident { $($variant:ident = $value:expr),* $(,)? }) => {
48 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
49 #[derive(Clone, Debug, PartialEq)]
50 pub enum $enum_name {
51 $($variant,)*
52 }
53
54 impl $enum_name {
55 pub fn as_str(&self) -> &'static str {
57 match self {
58 $(Self::$variant => stringify!($variant),)*
59 }
60 }
61 }
62
63 impl Serialize for $enum_name {
64 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65 where
66 S: serde::Serializer,
67 {
68 let s = match self {
71 $(Self::$variant => stringify!($variant),)*
72 };
73 serializer.serialize_str(s)
74 }
75 }
76
77 impl<'de> Deserialize<'de> for $enum_name {
78 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
79 where
80 D: serde::Deserializer<'de>,
81 {
82 struct Visitor;
83
84 impl<'de> serde::de::Visitor<'de> for Visitor {
85 type Value = $enum_name;
86
87 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
88 formatter.write_str(concat!("a valid ", stringify!($enum_name), " value"))
89 }
90
91 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
92 where
93 E: serde::de::Error,
94 {
95 match value {
96 $($value => Ok($enum_name::$variant),)*
97 _ => Err(E::custom(format!("invalid {} value: {}", stringify!($enum_name), value)))
98 }
99 }
100
101 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
102 where
103 E: serde::de::Error,
104 {
105 self.visit_i64(value as i64)
106 }
107
108 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
109 where
110 E: serde::de::Error,
111 {
112 match value {
113 $(stringify!($variant) => Ok($enum_name::$variant),)*
114 _ => Err(E::custom(format!("invalid {} value: {}", stringify!($enum_name), value)))
115 }
116 }
117 }
118
119 deserializer.deserialize_any(Visitor)
120 }
121 }
122
123 impl ApiEnum for $enum_name {
124 fn to_api_value(&self) -> i8 {
125 match self {
126 $(Self::$variant => $value,)*
127 }
128 }
129
130 fn from_string(s: &str) -> Option<Self> {
131 match s {
132 $(stringify!($variant) => Some(Self::$variant),)*
133 _ => None
134 }
135 }
136 }
137 };
138}
139
140macro_rules! impl_profile_preference_enum {
141 ($base:ident, $profile:ident, $preference:ident { $($variant:ident = $value:expr),* $(,)? }) => {
142 impl_numeric_string_enum! {
143 $base {
144 $($variant = $value,)*
145 }
146 }
147
148 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
149 #[derive(Clone, Debug, PartialEq)]
150 pub enum $profile {
151 PreferNotToSay,
152 $($variant,)*
153 }
154
155 impl $profile {
156 pub fn to_value(&self) -> Option<$base> {
158 match self {
159 Self::PreferNotToSay => None,
160 $(Self::$variant => Some($base::$variant),)*
161 }
162 }
163
164 pub fn from_value(value: $base) -> Self {
166 match value {
167 $($base::$variant => Self::$variant,)*
168 }
169 }
170
171 pub fn into_preference(self) -> Option<$preference> {
173 self.to_value().map($preference::from_value)
174 }
175 }
176
177 impl From<$base> for $profile {
178 fn from(value: $base) -> Self {
179 Self::from_value(value)
180 }
181 }
182
183 impl Serialize for $profile {
184 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
185 where
186 S: serde::Serializer,
187 {
188 match self {
189 Self::PreferNotToSay => serializer.serialize_str("PreferNotToSay"),
190 $(Self::$variant => serializer.serialize_str(stringify!($variant)),)*
191 }
192 }
193 }
194
195 impl<'de> Deserialize<'de> for $profile {
196 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
197 where
198 D: serde::Deserializer<'de>,
199 {
200 struct Visitor;
201
202 impl<'de> serde::de::Visitor<'de> for Visitor {
203 type Value = $profile;
204
205 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
206 formatter.write_str(concat!("a valid ", stringify!($profile), " value"))
207 }
208
209 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
210 where
211 E: serde::de::Error,
212 {
213 match value {
214 0 => Ok($profile::PreferNotToSay),
215 $($value => Ok($profile::$variant),)*
216 _ => Err(E::custom(format!("invalid {} value: {}", stringify!($profile), value))),
217 }
218 }
219
220 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
221 where
222 E: serde::de::Error,
223 {
224 self.visit_i64(value as i64)
225 }
226
227 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
228 where
229 E: serde::de::Error,
230 {
231 match value {
232 "PreferNotToSay" => Ok($profile::PreferNotToSay),
233 $(stringify!($variant) => Ok($profile::$variant),)*
234 _ => Err(E::custom(format!("invalid {} value: {}", stringify!($profile), value))),
235 }
236 }
237 }
238
239 deserializer.deserialize_any(Visitor)
240 }
241 }
242
243 impl ApiEnum for $profile {
244 fn to_api_value(&self) -> i8 {
245 match self {
246 Self::PreferNotToSay => 0,
247 $(Self::$variant => $value,)*
248 }
249 }
250
251 fn from_string(s: &str) -> Option<Self> {
252 match s {
253 "PreferNotToSay" => Some(Self::PreferNotToSay),
254 $(stringify!($variant) => Some(Self::$variant),)*
255 _ => None,
256 }
257 }
258 }
259
260 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
261 #[derive(Clone, Debug, PartialEq)]
262 pub enum $preference {
263 OpenToAll,
264 $($variant,)*
265 }
266
267 impl $preference {
268 pub fn to_value(&self) -> Option<$base> {
270 match self {
271 Self::OpenToAll => None,
272 $(Self::$variant => Some($base::$variant),)*
273 }
274 }
275
276 pub fn from_value(value: $base) -> Self {
278 match value {
279 $($base::$variant => Self::$variant,)*
280 }
281 }
282
283 pub fn into_profile(self) -> Option<$profile> {
285 self.to_value().map($profile::from_value)
286 }
287 }
288
289 impl From<$base> for $preference {
290 fn from(value: $base) -> Self {
291 Self::from_value(value)
292 }
293 }
294
295 impl Serialize for $preference {
296 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
297 where
298 S: serde::Serializer,
299 {
300 match self {
301 Self::OpenToAll => serializer.serialize_str("OpenToAll"),
302 $(Self::$variant => serializer.serialize_str(stringify!($variant)),)*
303 }
304 }
305 }
306
307 impl<'de> Deserialize<'de> for $preference {
308 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
309 where
310 D: serde::Deserializer<'de>,
311 {
312 struct Visitor;
313
314 impl<'de> serde::de::Visitor<'de> for Visitor {
315 type Value = $preference;
316
317 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
318 formatter.write_str(concat!("a valid ", stringify!($preference), " value"))
319 }
320
321 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
322 where
323 E: serde::de::Error,
324 {
325 match value {
326 -1 => Ok($preference::OpenToAll),
327 $($value => Ok($preference::$variant),)*
328 _ => Err(E::custom(format!("invalid {} value: {}", stringify!($preference), value))),
329 }
330 }
331
332 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
333 where
334 E: serde::de::Error,
335 {
336 self.visit_i64(value as i64)
337 }
338
339 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
340 where
341 E: serde::de::Error,
342 {
343 match value {
344 "OpenToAll" => Ok($preference::OpenToAll),
345 $(stringify!($variant) => Ok($preference::$variant),)*
346 _ => Err(E::custom(format!("invalid {} value: {}", stringify!($preference), value))),
347 }
348 }
349 }
350
351 deserializer.deserialize_any(Visitor)
352 }
353 }
354
355 impl ApiEnum for $preference {
356 fn to_api_value(&self) -> i8 {
357 match self {
358 Self::OpenToAll => -1,
359 $(Self::$variant => $value,)*
360 }
361 }
362
363 fn from_string(s: &str) -> Option<Self> {
364 match s {
365 "OpenToAll" => Some(Self::OpenToAll),
366 $(stringify!($variant) => Some(Self::$variant),)*
367 _ => None,
368 }
369 }
370 }
371 };
372}
373
374#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
375#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
376#[serde(rename_all = "lowercase")]
377pub enum ContentType {
378 Text,
379 Media,
380 Audio,
381 Video,
382 Voice,
383 Poll,
384}
385
386impl_profile_preference_enum! {
387 ChildrenStatusValue,
388 ChildrenStatusProfile,
389 ChildrenStatusPreference {
390 No = 1,
391 Yes = 2,
392 }
393}
394
395impl_profile_preference_enum! {
396 DatingIntentionValue,
397 DatingIntentionProfile,
398 DatingIntentionPreference {
399 LifePartner = 1,
400 LongTermRelationship = 2,
401 LongTermOpenToShort = 3,
402 ShortTermOpenToLong = 4,
403 ShortTermRelationship = 5,
404 FiguringOutTheirDatingGoals = 6,
405 }
406}
407
408impl_profile_preference_enum! {
409 DrinkingStatusValue,
410 DrinkingStatusProfile,
411 DrinkingStatusPreference {
412 No = 1,
413 Yes = 2,
414 Sometimes = 3,
415 }
416}
417
418impl_profile_preference_enum! {
419 SmokingStatusValue,
420 SmokingStatusProfile,
421 SmokingStatusPreference {
422 No = 1,
423 Yes = 2,
424 Sometimes = 3,
425 }
426}
427
428impl_profile_preference_enum! {
429 MarijuanaStatusValue,
430 MarijuanaStatusProfile,
431 MarijuanaStatusPreference {
432 No = 1,
433 Yes = 2,
434 Sometimes = 3,
435 NoPreference = 4,
436 }
437}
438
439impl_profile_preference_enum! {
440 DrugStatusValue,
441 DrugStatusProfile,
442 DrugStatusPreference {
443 No = 1,
444 Yes = 2,
445 Sometimes = 3,
446 }
447}
448
449impl_numeric_string_enum! {
450 GenderEnum {
451 Man = 0,
452 Woman = 1,
453 NonBinary = 3,
454 }
455}
456
457impl_numeric_string_enum! {
458 GenderPreferences {
459 Men = 0,
460 Women = 1,
461 Everyone = 2,
462 }
463}
464
465impl_profile_preference_enum! {
466 EthnicityValue,
467 EthnicityProfile,
468 EthnicityPreference {
469 AmericanIndian = 1,
470 BlackAfrican = 2,
471 EastAsian = 3,
472 Hispanic = 4,
473 MiddleEastern = 5,
474 PacificIslander = 6,
475 SouthAsian = 7,
476 White = 8,
477 Other = 9,
478 }
479}
480
481impl_profile_preference_enum! {
482 ReligionValue,
483 ReligionProfile,
484 ReligionPreference {
485 Spiritual = 1,
486 Catholic = 2,
487 Christian = 3,
488 Hindu = 4,
489 Jewish = 5,
490 Muslim = 6,
491 Buddhist = 7,
492 Agnostic = 8,
493 Atheist = 9,
494 Other = 10,
495 Sikh = 11,
496 }
497}
498
499impl_profile_preference_enum! {
500 PoliticsValue,
501 PoliticsProfile,
502 PoliticsPreference {
503 Liberal = 1,
504 Moderate = 2,
505 Conservative = 3,
506 NotPolitical = 4,
507 Other = 5,
508 }
509}
510
511impl_profile_preference_enum! {
512 EducationAttainedValue,
513 EducationAttainedProfile,
514 EducationAttainedPreference {
515 HighSchool = 1,
516 TradeSchool = 2,
517 InCollege = 3,
518 Undergraduate = 4,
519 InGradSchool = 5,
520 Graduate = 6,
521 }
522}
523
524impl_profile_preference_enum! {
525 RelationshipTypeValue,
526 RelationshipTypeProfile,
527 RelationshipTypePreference {
528 Monogamy = 1,
529 EthicalNonMonogamy = 2,
530 FiguringOutTheirRelationshipType = 3,
531 }
532}
533
534pub type QuestionId = String;
536
537#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
538#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
539#[serde(rename_all = "UPPERCASE")]
540pub enum LanguageEnum {
541 En,
542 Es,
543 Fr,
544 De,
545 It,
546 Pt,
547 Ru,
548 Zh,
549 Ja,
550 Ko,
551 Ar,
552 Hi,
553 Other,
554}