discogs_api/data_types/
fallible.rs

1use 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}