Skip to main content

topcoat_runtime/surrogate/
result.rs

1use ref_cast::RefCast;
2use serde::{Deserialize, Serialize};
3
4use crate::{
5    BoolSurrogate, OptionSurrogate, StrSurrogate, Surrogate, Surrogated, impl_surrogate,
6    impl_surrogate_mut, impl_surrogate_ref,
7};
8
9#[derive(Debug, Clone, RefCast)]
10#[repr(transparent)]
11pub struct ResultSurrogate<T, E>(Result<T, E>);
12
13impl<T, E> ResultSurrogate<T, E> {
14    #[inline]
15    pub(crate) const fn new(v: Result<T, E>) -> Self {
16        Self(v)
17    }
18
19    #[inline]
20    pub fn is_ok(&self) -> BoolSurrogate {
21        BoolSurrogate::new(self.0.is_ok())
22    }
23
24    #[inline]
25    pub fn is_err(&self) -> BoolSurrogate {
26        BoolSurrogate::new(self.0.is_err())
27    }
28
29    #[inline]
30    pub fn ok(self) -> OptionSurrogate<T> {
31        OptionSurrogate::new(self.0.ok())
32    }
33
34    #[inline]
35    pub fn err(self) -> OptionSurrogate<E> {
36        OptionSurrogate::new(self.0.err())
37    }
38}
39
40impl<T, E> ResultSurrogate<T, E> {
41    #[inline]
42    pub fn from_ok(v: impl Surrogate<Real = T>) -> Self {
43        Self(Result::Ok(v.into_real()))
44    }
45}
46
47impl<T, E> ResultSurrogate<T, E>
48where
49    T: Surrogated,
50    E: std::fmt::Debug,
51{
52    /// Returns the contained `Ok` value.
53    ///
54    /// # Panics
55    ///
56    /// Panics if the result is `Err`.
57    #[inline]
58    #[track_caller]
59    pub fn unwrap(self) -> T::Surrogate {
60        self.0.unwrap().into_surrogate()
61    }
62
63    /// Returns the contained `Ok` value, panicking with `msg` if `Err`.
64    ///
65    /// # Panics
66    ///
67    /// Panics with `msg` if the result is `Err`.
68    #[inline]
69    #[track_caller]
70    pub fn expect(self, msg: &StrSurrogate) -> T::Surrogate {
71        self.0.expect(&msg.0).into_surrogate()
72    }
73}
74
75impl<T, E> ResultSurrogate<T, E> {
76    #[inline]
77    pub fn from_err(v: impl Surrogate<Real = E>) -> Self {
78        Self(Result::Err(v.into_real()))
79    }
80}
81
82impl<T, E> ResultSurrogate<T, E>
83where
84    T: std::fmt::Debug,
85    E: Surrogated,
86{
87    #[inline]
88    #[track_caller]
89    pub fn unwrap_err(self) -> E::Surrogate {
90        self.0.unwrap_err().into_surrogate()
91    }
92
93    #[inline]
94    #[track_caller]
95    pub fn expect_err(self, msg: &StrSurrogate) -> E::Surrogate {
96        self.0.expect_err(&msg.to_string()).into_surrogate()
97    }
98}
99
100impl_surrogate!({T, E} Result<T, E>, ResultSurrogate<T, E>);
101impl_surrogate_ref!({T, E} Result<T, E>, ResultSurrogate<T, E>);
102impl_surrogate_mut!({T, E} Result<T, E>, ResultSurrogate<T, E>);
103
104#[derive(Serialize, Deserialize)]
105#[serde(untagged)]
106enum Body<T, E> {
107    Ok { t: String, ok: T },
108    Err { t: String, err: E },
109}
110
111impl<T, E> serde::Serialize for ResultSurrogate<T, E>
112where
113    for<'a> &'a T: Surrogated,
114    for<'a> <&'a T as Surrogated>::Surrogate: serde::Serialize,
115    for<'a> &'a E: Surrogated,
116    for<'a> <&'a E as Surrogated>::Surrogate: serde::Serialize,
117{
118    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
119    where
120        S: serde::Serializer,
121    {
122        let body = match &self.0 {
123            Result::Ok(v) => Body::Ok {
124                t: "Result".to_owned(),
125                ok: v.into_surrogate(),
126            },
127            Result::Err(e) => Body::Err {
128                t: "Result".to_owned(),
129                err: e.into_surrogate(),
130            },
131        };
132        body.serialize(serializer)
133    }
134}
135
136impl<'de, T, E> serde::Deserialize<'de> for ResultSurrogate<T, E>
137where
138    T: Surrogated,
139    T::Surrogate: serde::Deserialize<'de>,
140    E: Surrogated,
141    E::Surrogate: serde::Deserialize<'de>,
142{
143    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
144    where
145        D: serde::Deserializer<'de>,
146    {
147        let body = Body::<T::Surrogate, E::Surrogate>::deserialize(deserializer)?;
148        Ok(Self(match body {
149            Body::Ok { ok, .. } => Result::Ok(ok.into_real()),
150            Body::Err { err, .. } => Result::Err(err.into_real()),
151        }))
152    }
153}