acts/
error.rs

1use core::fmt;
2use serde::{Deserialize, Serialize};
3use std::{io::ErrorKind, string::FromUtf8Error};
4use thiserror::Error;
5
6use crate::{Result, Vars};
7
8#[derive(Deserialize, Serialize, Error, Debug, Clone, PartialEq)]
9pub enum ActError {
10    #[error("{0}")]
11    Config(String),
12
13    #[error("{0}")]
14    Convert(String),
15
16    #[error("{0}")]
17    Script(String),
18
19    #[error("ecode: {ecode}, message: {message}")]
20    Exception { ecode: String, message: String },
21
22    #[error("{0}")]
23    Model(String),
24
25    #[error("{0}")]
26    Runtime(String),
27
28    #[error("{0}")]
29    Store(String),
30
31    #[error("{0}")]
32    Action(String),
33
34    #[error("{0}")]
35    IoError(String),
36
37    #[error("{0}")]
38    Package(String),
39}
40
41#[derive(Default, Debug, Clone, Deserialize, Serialize)]
42pub struct Error {
43    #[serde(default)]
44    pub ecode: String,
45    #[serde(default)]
46    pub message: String,
47}
48
49impl fmt::Display for Error {
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        let text = serde_json::to_string(self).unwrap();
52        f.write_str(&text)
53    }
54}
55
56impl Error {
57    pub fn new(message: &str, ecode: &str) -> Self {
58        Self {
59            message: message.to_string(),
60            ecode: ecode.to_string(),
61        }
62    }
63
64    pub fn from_var(value: &Vars) -> Result<Self> {
65        serde_json::from_value::<Self>(value.clone().into()).map_err(|err| err.into())
66    }
67}
68
69impl From<ActError> for String {
70    fn from(val: ActError) -> Self {
71        val.to_string()
72    }
73}
74
75impl From<ActError> for Vars {
76    fn from(val: ActError) -> Self {
77        match val {
78            ActError::Exception { ecode, message } => {
79                Vars::new().with("ecode", ecode).with("message", message)
80            }
81            err => Vars::new()
82                .with("ecode", "")
83                .with("message", err.to_string()),
84        }
85    }
86}
87
88impl From<ActError> for Error {
89    fn from(val: ActError) -> Self {
90        match val {
91            ActError::Exception { ecode, message } => Error { ecode, message },
92            err => Error {
93                ecode: "".to_string(),
94                message: err.to_string(),
95            },
96        }
97    }
98}
99
100impl From<std::io::Error> for ActError {
101    fn from(error: std::io::Error) -> Self {
102        ActError::IoError(error.to_string())
103    }
104}
105
106impl From<ActError> for std::io::Error {
107    fn from(val: ActError) -> Self {
108        #[allow(clippy::io_other_error)]
109        std::io::Error::new(ErrorKind::Other, val.to_string())
110    }
111}
112
113impl From<rquickjs::Error> for ActError {
114    fn from(error: rquickjs::Error) -> Self {
115        ActError::Script(error.to_string())
116    }
117}
118
119impl From<ActError> for rquickjs::Error {
120    fn from(val: ActError) -> Self {
121        std::io::Error::other(val.to_string()).into()
122    }
123}
124
125impl From<FromUtf8Error> for ActError {
126    fn from(_: FromUtf8Error) -> Self {
127        ActError::Runtime("Error with utf-8 string convert".to_string())
128    }
129}
130
131impl From<serde_json::Error> for ActError {
132    fn from(error: serde_json::Error) -> Self {
133        ActError::Convert(error.to_string())
134    }
135}
136
137impl<'a> From<rquickjs::CaughtError<'a>> for ActError {
138    fn from(error: rquickjs::CaughtError<'a>) -> Self {
139        ActError::Script(error.to_string())
140    }
141}
142
143impl From<jsonschema::ValidationError<'_>> for ActError {
144    fn from(error: jsonschema::ValidationError<'_>) -> Self {
145        ActError::Runtime(error.to_string())
146    }
147}
148
149#[cfg(test)]
150mod tests {
151    use serde_json::json;
152
153    use crate::{ActError, Error, Vars};
154
155    #[test]
156    fn engine_error_default() {
157        let err = Error::default();
158        assert_eq!(err.message, "");
159        assert_eq!(err.ecode, "");
160    }
161
162    #[test]
163    fn engine_error_json_full() {
164        let err = Error::new("abc", "err1");
165        let v = serde_json::to_value(err).unwrap();
166        assert_eq!(v, json!({ "ecode": "err1", "message": "abc" }))
167    }
168
169    #[test]
170    fn engine_error_from_value() {
171        let err = Vars::new().with("ecode", "err1").with("message", "test");
172        let v = Error::from_var(&err).unwrap();
173        assert_eq!(v.ecode, "err1");
174        assert_eq!(v.message, "test");
175    }
176
177    #[test]
178    fn engine_act_error_into() {
179        let err = ActError::Action("error message".to_string());
180        let v: Error = err.into();
181        assert_eq!(v.message, "error message");
182        assert_eq!(v.ecode, "");
183    }
184
185    #[test]
186    fn engine_act_exception_into() {
187        let err = ActError::Exception {
188            ecode: "err1".to_string(),
189            message: "error message".to_string(),
190        };
191        let v: Error = err.into();
192        assert_eq!(v.message, "error message");
193        assert_eq!(v.ecode, "err1");
194    }
195}