ts_bindgen_rt/jsvalue_serde/
error.rs

1use js_sys::{Error as JsError, Reflect};
2use serde::{de, ser};
3use std::error;
4use std::fmt::{Display, Formatter};
5use wasm_bindgen::JsValue;
6
7pub type Result<R> = std::result::Result<R, Error>;
8
9/// Error type for serde errors
10#[derive(Debug, Clone)]
11pub enum Error {
12    /// A custom error with a message
13    Custom(String),
14    /// An error indicating that an invalid type was found
15    InvalidType(String),
16    /// A javascript error occured
17    JsError {
18        /// The message from the javascript error
19        msg: Option<String>,
20        /// The stack from the javascript error
21        stack: Option<String>,
22    },
23}
24
25impl From<JsValue> for Error {
26    fn from(src: JsValue) -> Self {
27        let msg_key: JsValue = "message".into();
28        let msg = if Reflect::has(&src, &msg_key).unwrap_or(false) {
29            Reflect::get(&src, &msg_key)
30                .map(|v| v.as_string())
31                .unwrap_or(None)
32        } else {
33            None
34        };
35
36        let stack_key: JsValue = "stack".into();
37        let stack = if Reflect::has(&src, &stack_key).unwrap_or(false) {
38            Reflect::get(&src, &stack_key)
39                .map(|v| v.as_string())
40                .unwrap_or(None)
41        } else {
42            None
43        };
44
45        Error::JsError { msg, stack }
46    }
47}
48
49impl From<Error> for JsValue {
50    fn from(src: Error) -> Self {
51        JsError::new(&src.to_string()).into()
52    }
53}
54
55impl Display for Error {
56    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
57        write!(f, "jsvalue_serde error: {:?}", self)
58    }
59}
60
61impl de::StdError for Error {
62    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
63        None
64    }
65}
66
67impl ser::Error for Error {
68    fn custom<T: Display>(msg: T) -> Error {
69        Error::Custom(format!("{}", msg))
70    }
71}
72
73impl de::Error for Error {
74    fn custom<T: Display>(msg: T) -> Error {
75        Error::Custom(format!("{}", msg))
76    }
77
78    fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
79        Error::InvalidType(format!("received {}, expected {}", unexp, exp))
80    }
81}
82
83pub trait ExpectValue<T> {
84    fn expect_value(self, msg: &str) -> Result<T>;
85}
86
87impl<T> ExpectValue<T> for Option<T> {
88    fn expect_value(self, msg: &str) -> Result<T> {
89        if let Some(val) = self {
90            Ok(val)
91        } else {
92            Err(Error::InvalidType(format!("expected: {}", msg)))
93        }
94    }
95}