ts_bindgen_rt/jsvalue_serde/
error.rs1use 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#[derive(Debug, Clone)]
11pub enum Error {
12 Custom(String),
14 InvalidType(String),
16 JsError {
18 msg: Option<String>,
20 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}