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