syndicate/
error.rs

1//! Actor errors.
2
3use super::actor::AnyValue;
4use super::language;
5use super::schemas::protocol as P;
6
7use preserves::value::NestedValue;
8use preserves::value::Value;
9use preserves_schema::Codec;
10use preserves_schema::ParseError;
11
12pub type Error = P::Error<AnyValue>;
13
14impl Error {
15    /// Construct an [`Error`] given a displayable `T`.
16    /// Uses the displayed form of the `T` as `message`, and `false` as detail (per convention).
17    ///
18    /// This function is useful to translate [`std::error::Error`] from some other API
19    /// into Syndicate `Error`:
20    ///
21    /// ```
22    /// return some_operation().map_err(Error::msg)
23    /// ```
24    pub fn msg<T: std::fmt::Display>(e: T) -> Self {
25        error(&e.to_string(), AnyValue::new(false))
26    }
27}
28
29impl std::error::Error for Error {}
30
31impl std::fmt::Display for Error {
32    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
33        write!(f, "Error: {}; detail: {:?}", self.message, self.detail)
34    }
35}
36
37/// Construct an [`Error`] with the given `message` and `detail`; see also [`Error::msg`].
38///
39/// When no relevant detail exists, convention is to set `detail` to `false`.
40pub fn error<Detail>(message: &str, detail: Detail) -> Error where AnyValue: From<Detail> {
41    Error {
42        message: message.to_owned(),
43        detail: AnyValue::from(detail),
44    }
45}
46
47/// Encodes an [`ActorResult`][crate::actor::ActorResult] as an [`AnyValue`].
48///
49/// Used primarily when attempting to perform an
50/// [`Activation`][crate::actor::Activation] on an already-terminated
51/// actor.
52pub fn encode_error(result: Result<(), Error>) -> AnyValue {
53    match result {
54        Ok(()) => {
55            let mut r = Value::record(AnyValue::symbol("Ok"), 1);
56            r.fields_vec_mut().push(Value::record(AnyValue::symbol("tuple"), 0).finish().wrap());
57            r.finish().wrap()
58        }
59        Err(e) => {
60            let mut r = Value::record(AnyValue::symbol("Err"), 1);
61            r.fields_vec_mut().push(language().unparse(&e));
62            r.finish().wrap()
63        }
64    }
65}
66
67impl<'a> From<&'a str> for Error {
68    fn from(v: &'a str) -> Self {
69        error(v, AnyValue::new(false))
70    }
71}
72
73impl From<std::io::Error> for Error {
74    fn from(v: std::io::Error) -> Self {
75        error(&format!("{}", v), AnyValue::new(false))
76    }
77}
78
79impl From<ParseError> for Error {
80    fn from(v: ParseError) -> Self {
81        error(&format!("{}", v), AnyValue::new(false))
82    }
83}
84
85impl From<preserves::error::Error> for Error {
86    fn from(v: preserves::error::Error) -> Self {
87        error(&format!("{}", v), AnyValue::new(false))
88    }
89}
90
91impl From<Box<dyn std::error::Error>> for Error {
92    fn from(v: Box<dyn std::error::Error>) -> Self {
93        match v.downcast::<Error>() {
94            Ok(e) => *e,
95            Err(v) => error(&format!("{}", v), AnyValue::new(false)),
96        }
97    }
98}
99
100impl From<Box<dyn std::error::Error + Send + Sync + 'static>> for Error {
101    fn from(v: Box<dyn std::error::Error + Send + Sync + 'static>) -> Self {
102        match v.downcast::<Error>() {
103            Ok(e) => *e,
104            Err(v) => error(&format!("{}", v), AnyValue::new(false)),
105        }
106    }
107}