1 pub use helper::*;
2 
3 pub trait TypescriptResult: From<WasmResult> {
4     type RustType;
5 }
6 
7 macro_rules! result_type {
8   ($ty:ty, $name:ident, $stringified:literal) => {
9     #[wasm_bindgen]
10     extern "C" {
11       #[wasm_bindgen(typescript_type = $stringified)]
12       pub type $name;
13     }
14     impl From<$crate::wasm_result::WasmResult> for $name {
15       fn from(other: $crate::wasm_result::WasmResult) -> Self {
16         let jsv: JsValue = other.into();
17         $name::from(jsv)
18       }
19     }
20     impl TypescriptResult for $name {
21         type RustType = $ty;
22     }
23   };
24 }
25 
26 #[allow(dead_code)]
27 mod helper {
28     use wasm_bindgen::prelude::*;
29     use js_sys::Error as JsError;
30     use serde::Serialize;
31     use super::TypescriptResult;
32     use crate::{DriverError, CiteprocRsDriverError, CiteprocRsError, CslStyleError};
33     use csl::StyleError;
34 
35     crate::js_import_class_constructor! {
36         pub type WasmResult;
37         #[wasm_bindgen(constructor)]
38         fn new(value: JsValue) -> WasmResult;
39     }
40 
js_value_err<V, E, F>(f: F) -> WasmResult where V: Into<JsValue>, E: std::error::Error, F: FnOnce() -> Result<V, E>,41     pub fn js_value_err<V, E, F>(f: F) -> WasmResult
42     where
43         V: Into<JsValue>,
44         E: std::error::Error,
45         F: FnOnce() -> Result<V, E>,
46     {
47         let res = f();
48         let out = match res {
49             Ok(ok) => {
50                 WasmResult::new(ok.into())
51             }
52             Err(e) => {
53                 WasmResult::new(JsError::new(&e.to_string()).into())
54             }
55         };
56         out
57     }
58 
style_error_to_js_err(se: &StyleError) -> JsValue59     fn style_error_to_js_err(se: &StyleError) -> JsValue {
60         let mut string = se.to_string();
61         let data = JsValue::from_serde(&se);
62         match data {
63             Ok(data) => CslStyleError::new(string.into(), data).into(),
64             Err(conv_err) => {
65                 string.push_str(" (could not convert error data: ");
66                 string.push_str(&conv_err.to_string());
67                 string.push_str(") ");
68                 CiteprocRsError::new(string.into()).into()
69             },
70         }
71     }
72 
73     impl DriverError {
to_js_error(&self) -> JsValue74         fn to_js_error(&self) -> JsValue {
75             match self {
76                 DriverError::StyleError(se) => return style_error_to_js_err(se),
77                 _ => {}
78             }
79             let mut string = self.to_string();
80             let data = JsValue::from_serde(&self);
81             match data {
82                 Ok(data) => CiteprocRsDriverError::new(string.into(), data).into(),
83                 Err(conv_err) => {
84                     string.push_str(" (could not convert error data: ");
85                     string.push_str(&conv_err.to_string());
86                     string.push_str(") ");
87                     CiteprocRsError::new(string.into()).into()
88                 },
89             }
90         }
91     }
92 
93     impl From<Result<JsValue, DriverError>> for WasmResult {
from(res: Result<JsValue, DriverError>) -> Self94         fn from(res: Result<JsValue, DriverError>) -> Self {
95             match res {
96                 Ok(ok) => {
97                     WasmResult::new(ok.into())
98                 }
99                 Err(e) => {
100                     WasmResult::new(e.to_js_error())
101                 }
102             }
103         }
104     }
105 
js_driver_error<V, F>(f: F) -> WasmResult where V: Into<JsValue>, F: FnOnce() -> Result<V, DriverError>,106     pub fn js_driver_error<V, F>(f: F) -> WasmResult
107     where
108         V: Into<JsValue>,
109         F: FnOnce() -> Result<V, DriverError>,
110     {
111         f().map(|x| x.into()).into()
112     }
113 
typescript_serde_result<R, F>(f: F) -> R where R: TypescriptResult, R::RustType: Serialize, F: FnOnce() -> Result<R::RustType, DriverError>,114     pub fn typescript_serde_result<R, F>(f: F) -> R
115     where
116         R: TypescriptResult,
117         R::RustType: Serialize,
118         F: FnOnce() -> Result<R::RustType, DriverError>,
119     {
120         let res = f()
121             .and_then(|rust| {
122                 JsValue::from_serde(&rust)
123                     .map_err(DriverError::from)
124             });
125         let out: WasmResult = res.into();
126         out.into()
127     }
128 
129 }
130 
131 #[allow(dead_code)]
132 mod raw {
133     //! Alternative impl with no Javascript dependency but no methods available
134     //! on the returned objects.
135 
136     use wasm_bindgen::prelude::*;
137     use js_sys::Error as JsError;
138     use serde::Serialize;
139 
140     pub type WasmResult = JsValue;
141 
142     // From serde_wasm_bindgen
143     /// Custom bindings to avoid using fallible `Reflect` for plain objects.
144     #[wasm_bindgen]
145     extern "C" {
146         pub type Object;
147 
148         #[wasm_bindgen(constructor)]
new() -> Object149         pub fn new() -> Object;
150 
151         #[wasm_bindgen(method, indexing_setter)]
set(this: &Object, key: JsValue, value: JsValue)152         pub fn set(this: &Object, key: JsValue, value: JsValue);
153     }
154 
155     thread_local! {
156         pub static OK_FIELD: JsValue = JsValue::from_str("Ok");
157         pub static ERR_FIELD: JsValue = JsValue::from_str("Err");
158     }
159 
js_value_err<E, F>(f: F) -> JsValue where E: std::error::Error, F: FnOnce() -> Result<JsValue, E>,160     pub fn js_value_err<E, F>(f: F) -> JsValue
161     where
162         E: std::error::Error,
163         F: FnOnce() -> Result<JsValue, E>,
164     {
165         let res = f();
166         let out = Object::new();
167         match res {
168             Ok(ok) => {
169                 out.set(OK_FIELD.with(|f| f.clone()), ok);
170             }
171             Err(e) => {
172                 out.set(
173                     ERR_FIELD.with(|f| f.clone()),
174                     JsError::new(&e.to_string()).into(),
175                 );
176             }
177         }
178         out.into()
179     }
180 
js_serde_err<T, E, F>(f: F) -> JsValue where T: Serialize, E: std::error::Error, F: FnOnce() -> Result<T, E>,181     pub fn js_serde_err<T, E, F>(f: F) -> JsValue
182     where
183         T: Serialize,
184         E: std::error::Error,
185         F: FnOnce() -> Result<T, E>,
186     {
187         let res = f();
188         let out = Object::new();
189         match res {
190             Ok(ok) => {
191                 let value = JsValue::from_serde(&ok)
192                     .expect("citeproc-wasm failed to serialize return value to JsValue");
193                 out.set(OK_FIELD.with(|f| f.clone()), value);
194             }
195             Err(e) => {
196                 out.set(
197                     ERR_FIELD.with(|f| f.clone()),
198                     JsError::new(&e.to_string()).into(),
199                 );
200             }
201         }
202         out.into()
203     }
204 }
205 
206