ractor/rpc/
call_result.rs

1// Copyright (c) Sean Lawlor
2//
3// This source code is licensed under both the MIT license found in the
4// LICENSE-MIT file in the root directory of this source tree.
5
6//! This module contains the remote procedure call's [CallResult] structure
7//! and supported operations
8
9/// The result from a [crate::rpc::call] operation
10#[derive(Debug, Eq, PartialEq)]
11pub enum CallResult<TResult> {
12    /// Success, with the result
13    Success(TResult),
14    /// Timeout
15    Timeout,
16    /// The transmission channel was dropped without any message(s) being sent
17    SenderError,
18}
19
20impl<T> CallResult<T> {
21    /// Determine if the [CallResult] is a [CallResult::Success]
22    pub fn is_success(&self) -> bool {
23        matches!(self, Self::Success(_))
24    }
25
26    /// Determine if the [CallResult] is a [CallResult::Timeout]
27    pub fn is_timeout(&self) -> bool {
28        matches!(self, Self::Timeout)
29    }
30
31    /// Determine if the [CallResult] is a [CallResult::SenderError]
32    pub fn is_send_error(&self) -> bool {
33        matches!(self, Self::SenderError)
34    }
35
36    /// Unwrap a [CallResult], panicking on any non-success
37    pub fn unwrap(self) -> T {
38        match self {
39            Self::Success(t) => t,
40            Self::Timeout => panic!("called CallResult::<T>::unwrap()  on a `Timeout` value"),
41            Self::SenderError => {
42                panic!("called CallResult::<T>::unwrap() on a `SenderError` value")
43            }
44        }
45    }
46
47    /// Unwrap a [CallResult], panicking on non-succcess with the specified message
48    pub fn expect(self, msg: &'static str) -> T {
49        match self {
50            Self::Success(t) => t,
51            Self::Timeout => {
52                panic!("{msg} - called CallResult::<T>::expect()  on a `Timeout` value")
53            }
54            Self::SenderError => {
55                panic!("{msg} - called CallResult::<T>::expect() on a `SenderError` value")
56            }
57        }
58    }
59
60    /// Unwrap the [CallResult] or give a default value
61    pub fn unwrap_or(self, default: T) -> T {
62        if let Self::Success(t) = self {
63            t
64        } else {
65            default
66        }
67    }
68
69    /// Returns the [CallResult]'s success result or computes the closure
70    pub fn unwrap_or_else<F>(self, f: F) -> T
71    where
72        F: FnOnce() -> T,
73    {
74        if let Self::Success(t) = self {
75            t
76        } else {
77            f()
78        }
79    }
80
81    /// Transforms the [CallResult] to a Result mapping `Success(t)` to `Ok(t)` and all else to `Err(err)`
82    pub fn success_or<E>(self, err: E) -> Result<T, E> {
83        if let Self::Success(t) = self {
84            Ok(t)
85        } else {
86            Err(err)
87        }
88    }
89
90    /// Transforms the [CallResult] to a Result mapping `Success(t)` to `Ok(t)` and all else to `Err(err())`
91    pub fn success_or_else<E, F>(self, err: F) -> Result<T, E>
92    where
93        F: FnOnce() -> E,
94    {
95        if let Self::Success(t) = self {
96            Ok(t)
97        } else {
98            Err(err())
99        }
100    }
101
102    /// Maps the success value of the [CallResult] to another type
103    pub fn map<O, F>(self, mapping: F) -> CallResult<O>
104    where
105        F: FnOnce(T) -> O,
106    {
107        match self {
108            Self::Success(t) => CallResult::Success(mapping(t)),
109            Self::Timeout => CallResult::Timeout,
110            Self::SenderError => CallResult::SenderError,
111        }
112    }
113
114    /// Maps the success value of the [CallResult] to another type
115    /// or returns the default value
116    pub fn map_or<O, F>(self, default: O, mapping: F) -> O
117    where
118        F: FnOnce(T) -> O,
119    {
120        match self {
121            Self::Success(t) => mapping(t),
122            Self::Timeout => default,
123            Self::SenderError => default,
124        }
125    }
126
127    /// Maps the success value of the [CallResult] to another type
128    /// or returns the default function result
129    pub fn map_or_else<D, O, F>(self, default: D, mapping: F) -> O
130    where
131        F: FnOnce(T) -> O,
132        D: FnOnce() -> O,
133    {
134        match self {
135            Self::Success(t) => mapping(t),
136            Self::Timeout => default(),
137            Self::SenderError => default(),
138        }
139    }
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145
146    fn ok() -> CallResult<()> {
147        CallResult::Success(())
148    }
149    fn timeout() -> CallResult<()> {
150        CallResult::Timeout
151    }
152    fn err() -> CallResult<()> {
153        CallResult::SenderError
154    }
155
156    #[test]
157    fn test_call_result_operations() {
158        assert!(ok().is_success());
159        assert!(!ok().is_send_error());
160        assert!(!ok().is_timeout());
161
162        ok().unwrap();
163        ok().expect("Not ok!");
164        assert_eq!(1, ok().map(|_| 1).unwrap_or(2));
165        assert_eq!(1, ok().map(|_| 1).unwrap_or_else(|| 2));
166        assert_eq!(Ok(1), ok().map(|_| 1).success_or(2));
167        assert_eq!(Ok(1), ok().map(|_| 1).success_or_else(|| 2));
168        assert_eq!(1, ok().map_or(2, |_| 1));
169        assert_eq!(1, ok().map_or_else(|| 2, |_| 1));
170
171        assert!(!timeout().is_success());
172        assert!(!timeout().is_send_error());
173        assert!(timeout().is_timeout());
174
175        assert_eq!(2, timeout().map(|_| 1).unwrap_or(2));
176        assert_eq!(2, timeout().map(|_| 1).unwrap_or_else(|| 2));
177        assert_eq!(Err(2), timeout().map(|_| 1).success_or(2));
178        assert_eq!(Err(2), timeout().map(|_| 1).success_or_else(|| 2));
179        assert_eq!(2, timeout().map_or(2, |_| 1));
180        assert_eq!(2, timeout().map_or_else(|| 2, |_| 1));
181
182        assert!(!err().is_success());
183        assert!(err().is_send_error());
184        assert!(!err().is_timeout());
185
186        assert_eq!(2, err().map(|_| 1).unwrap_or(2));
187        assert_eq!(2, err().map(|_| 1).unwrap_or_else(|| 2));
188        assert_eq!(Err(2), err().map(|_| 1).success_or(2));
189        assert_eq!(Err(2), err().map(|_| 1).success_or_else(|| 2));
190        assert_eq!(2, err().map_or(2, |_| 1));
191        assert_eq!(2, err().map_or_else(|| 2, |_| 1));
192    }
193
194    #[test]
195    #[should_panic]
196    fn unwrap_timeout_panics() {
197        timeout().unwrap();
198    }
199
200    #[test]
201    #[should_panic]
202    fn expect_timeout_panics() {
203        timeout().expect("Should panic!");
204    }
205
206    #[test]
207    #[should_panic]
208    fn unwrap_err_panics() {
209        timeout().unwrap();
210    }
211
212    #[test]
213    #[should_panic]
214    fn expect_err_panics() {
215        timeout().expect("Should panic!");
216    }
217}