discogs_api/data_types/
fallible.rs1use serde::Deserialize;
2
3#[derive(Debug, Clone, Deserialize)]
4#[serde(untagged)]
5pub enum Fallible<R> {
6 Ok(R),
7 FailureMessage { message: String },
8}
9
10impl<R> Fallible<R> {
11 #[must_use]
12 pub fn ok(self) -> Option<R> {
13 if let Self::Ok(r) = self {
14 Some(r)
15 } else {
16 None
17 }
18 }
19
20 #[must_use]
21 pub fn err(self) -> Option<String> {
22 if let Self::FailureMessage { message } = self {
23 Some(message)
24 } else {
25 None
26 }
27 }
28
29 pub fn to_result(&self) -> Result<&R, &String> {
30 Result::from(self)
31 }
32
33 pub fn unwrap(&self) -> &R {
34 self.to_result().unwrap()
35 }
36}
37
38impl<'a, R> From<&'a Fallible<R>> for Result<&'a R, &'a String> {
39 fn from(value: &'a Fallible<R>) -> Self {
40 match value {
41 Fallible::Ok(r) => Ok(r),
42 Fallible::FailureMessage { message } => Err(message),
43 }
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::Fallible;
50 use serde::Deserialize;
51
52 #[derive(Deserialize)]
53 struct OkVariant {
54 pub abc: i32,
55 pub foo: Vec<String>,
56 }
57
58 #[test]
59 fn ok() {
60 let json = r#"{"abc": 123, "foo": ["b", "a", "r"]}"#;
61 let parsed = serde_json::from_str::<Fallible<OkVariant>>(json)
62 .unwrap()
63 .ok()
64 .expect("expected `Fallible::Ok` but got `Fallible::FailureMessage`");
65 assert_eq!(parsed.abc, 123);
66 assert_eq!(&parsed.foo, &["b", "a", "r"]);
67 }
68
69 #[test]
70 fn failure() {
71 let json = r#"{"message": "foo"}"#;
72 let parsed = serde_json::from_str::<Fallible<OkVariant>>(json)
73 .unwrap()
74 .err()
75 .expect("expected `Fallible::FailureMessage` but got `Fallible::Ok`");
76 assert_eq!(&parsed, "foo");
77 }
78}