ts_bindgen_rt/
lib.rs

1#![deny(missing_docs)]
2
3//! ts-bindgen-rt is the runtime library that ts-bindgen bindings depend on.
4
5extern crate js_sys;
6extern crate wasm_bindgen;
7
8pub mod jsvalue_serde;
9
10pub use jsvalue_serde::{from_jsvalue, to_jsvalue};
11use jsvalue_serde::{Error as SerdeError, JSVALUE_NEWTYPE_STRUCT, UNDEFINED_UNIT_STRUCT};
12use serde::{de, ser};
13use std::fmt;
14use wasm_bindgen::{
15    convert::{FromWasmAbi, IntoWasmAbi},
16    JsCast, JsValue,
17};
18
19/// Represents a null in javascript
20pub struct Null;
21
22/// Represents undefined in javascript
23pub struct Undefined;
24
25/// Error for any fallible ts-bindgen-rt operations
26#[derive(Debug)]
27pub struct Error;
28
29impl fmt::Display for Error {
30    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
31        write!(f, "Error")
32    }
33}
34
35impl std::error::Error for Error {
36    fn description(&self) -> &str {
37        "Error"
38    }
39}
40
41impl From<Error> for JsValue {
42    fn from(_: Error) -> JsValue {
43        js_sys::Error::new("rust failure").into()
44    }
45}
46
47impl From<JsValue> for Error {
48    fn from(_: JsValue) -> Error {
49        Error
50    }
51}
52
53impl From<serde_json::Error> for Error {
54    fn from(_: serde_json::Error) -> Error {
55        Error
56    }
57}
58
59impl From<Box<dyn std::error::Error>> for Error {
60    fn from(_: Box<dyn std::error::Error>) -> Error {
61        Error
62    }
63}
64
65impl From<SerdeError> for Error {
66    fn from(_: SerdeError) -> Error {
67        Error
68    }
69}
70
71/// Deserialize the JsValue into the requested type
72pub fn deserialize_as_jsvalue<'de, D, R>(deserializer: D) -> Result<R, D::Error>
73where
74    D: de::Deserializer<'de>,
75    R: JsCast,
76{
77    struct JsValueVisitor;
78
79    impl<'de> de::Visitor<'de> for JsValueVisitor {
80        type Value = JsValue;
81
82        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
83            formatter.write_str("u32 JsValue index")
84        }
85
86        fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
87        where
88            E: de::Error,
89        {
90            Ok(unsafe { FromWasmAbi::from_abi(value) })
91        }
92    }
93
94    let jsv = deserializer.deserialize_any(JsValueVisitor)?;
95    jsv.dyn_into().map_err(|_| {
96        de::Error::invalid_type(de::Unexpected::Other("bad dynamic cast"), &JsValueVisitor)
97    })
98}
99
100/// Serialize the provided value into a JsValue
101pub fn serialize_as_jsvalue<S, V>(serializer: S, value: &V) -> Result<S::Ok, S::Error>
102where
103    S: ser::Serializer,
104    V: Clone + IntoWasmAbi<Abi = u32>,
105{
106    let idx = value.clone().into_abi();
107    serializer.serialize_newtype_struct(JSVALUE_NEWTYPE_STRUCT, &idx)
108}
109
110/// Serialize the provided value into a JsValue
111pub fn serialize_jsvalue<S, V>(value: &V, serializer: S) -> Result<S::Ok, S::Error>
112where
113    S: ser::Serializer,
114    V: Clone + IntoWasmAbi<Abi = u32>,
115{
116    serialize_as_jsvalue(serializer, value)
117}
118
119/// Serialize a javascript undefined
120pub fn serialize_undefined<S>(serializer: S) -> Result<S::Ok, S::Error>
121where
122    S: ser::Serializer,
123{
124    serializer.serialize_unit_struct(UNDEFINED_UNIT_STRUCT)
125}
126
127/// Deserialize a javascript undefined
128pub fn deserialize_undefined<'de, D>(deserializer: D) -> Result<(), D::Error>
129where
130    D: de::Deserializer<'de>,
131{
132    struct JsValueVisitor;
133
134    impl<'de> de::Visitor<'de> for JsValueVisitor {
135        type Value = ();
136
137        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
138            formatter.write_str("newtype then none, representing undefined")
139        }
140
141        fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
142        where
143            D: de::Deserializer<'de>,
144        {
145            deserializer.deserialize_any(self)
146        }
147
148        fn visit_none<E>(self) -> Result<Self::Value, E>
149        where
150            E: de::Error,
151        {
152            Ok(())
153        }
154    }
155
156    // we deserialize undefined's as newtypes wrapping a none
157    // TODO: can't figure out why we can't call deserialize_unit here
158    deserializer.deserialize_any(JsValueVisitor)
159}