1 extern crate cfg_if;
2 extern crate js_sys;
3 extern crate jsonpath_lib as jsonpath;
4 extern crate serde_json;
5 extern crate wasm_bindgen;
6
7 use cfg_if::cfg_if;
8 use jsonpath::Selector as _Selector;
9 use jsonpath::SelectorMut as _SelectorMut;
10 use jsonpath::{JsonPathError, Parser};
11 use serde_json::Value;
12 use wasm_bindgen::prelude::*;
13
14 cfg_if! {
15 if #[cfg(feature = "wee_alloc")] {
16 extern crate wee_alloc;
17 #[global_allocator]
18 static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
19 }
20 }
21
22 cfg_if! {
23 if #[cfg(feature = "console_error_panic_hook")] {
24 extern crate console_error_panic_hook;
25 pub use self::console_error_panic_hook::set_once as set_panic_hook;
26 } else {
27 #[inline]
28 pub fn set_panic_hook() {}
29 }
30 }
31
32 #[wasm_bindgen]
33 extern "C" {
34 #[wasm_bindgen(js_namespace = console)]
error(s: &str)35 fn error(s: &str);
36 }
37
38 macro_rules! console_error {
39 ($($t:tt)*) => (error(&format_args!($($t)*).to_string()))
40 }
41
into_serde_json<D>(js_value: &JsValue) -> Result<D, String> where D: for<'a> serde::de::Deserialize<'a>,42 fn into_serde_json<D>(js_value: &JsValue) -> Result<D, String>
43 where
44 D: for<'a> serde::de::Deserialize<'a>,
45 {
46 if js_value.is_string() {
47 match serde_json::from_str(js_value.as_string().unwrap().as_str()) {
48 Ok(json) => Ok(json),
49 Err(e) => Err(e.to_string()),
50 }
51 } else {
52 match js_value.into_serde() {
53 Ok(json) => Ok(json),
54 Err(e) => Err(e.to_string()),
55 }
56 }
57 }
58
59 #[allow(clippy::unnecessary_wraps)]
replace_fun(v: Value, fun: &js_sys::Function) -> Option<Value>60 fn replace_fun(v: Value, fun: &js_sys::Function) -> Option<Value> {
61 match JsValue::from_serde(&v) {
62 Ok(js_v) => match fun.call1(&JsValue::NULL, &js_v) {
63 Ok(result) => match into_serde_json(&result) {
64 Ok(json) => Some(json),
65 Err(e) => {
66 console_error!("replace_with - closure returned a invalid JSON: {:?}", e);
67 Some(Value::Null)
68 }
69 },
70 Err(e) => {
71 console_error!("replace_with - fail to call closure: {:?}", e);
72 Some(Value::Null)
73 }
74 },
75 Err(e) => {
76 console_error!("replace_with - invalid JSON object: {:?}", e);
77 Some(Value::Null)
78 }
79 }
80 }
81
82 #[wasm_bindgen]
compile(path: &str) -> JsValue83 pub fn compile(path: &str) -> JsValue {
84 let node = Parser::compile(path);
85
86 if let Err(e) = &node {
87 return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e.clone())));
88 };
89
90 let cb = Closure::wrap(Box::new(move |js_value: JsValue| {
91 let json = match into_serde_json(&js_value) {
92 Ok(json) => json,
93 Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))),
94 };
95
96 let mut selector = _Selector::new();
97
98 match &node {
99 Ok(node) => selector.compiled_path(node),
100 Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e.clone()))),
101 };
102
103 match selector.value(&json).select() {
104 Ok(ret) => match JsValue::from_serde(&ret) {
105 Ok(ret) => ret,
106 Err(e) => JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string()))),
107 },
108 Err(e) => JsValue::from_str(&format!("{:?}", e)),
109 }
110 }) as Box<dyn Fn(JsValue) -> JsValue>);
111
112 let ret = cb.as_ref().clone();
113 cb.forget();
114 ret
115 }
116
117 #[wasm_bindgen]
selector(js_value: JsValue) -> JsValue118 pub fn selector(js_value: JsValue) -> JsValue {
119 let json: Value = match JsValue::into_serde(&js_value) {
120 Ok(json) => json,
121 Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string()))),
122 };
123
124 let cb = Closure::wrap(
125 Box::new(move |path: String| match Parser::compile(path.as_str()) {
126 Ok(node) => {
127 let mut selector = _Selector::new();
128 let _ = selector.compiled_path(&node);
129 match selector.value(&json).select() {
130 Ok(ret) => match JsValue::from_serde(&ret) {
131 Ok(ret) => ret,
132 Err(e) => {
133 JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string())))
134 }
135 },
136 Err(e) => JsValue::from_str(&format!("{:?}", e)),
137 }
138 }
139 Err(e) => JsValue::from_str(&format!("{:?}", JsonPathError::Path(e))),
140 }) as Box<dyn Fn(String) -> JsValue>,
141 );
142
143 let ret = cb.as_ref().clone();
144 cb.forget();
145 ret
146 }
147
148 #[wasm_bindgen]
select(js_value: JsValue, path: &str) -> JsValue149 pub fn select(js_value: JsValue, path: &str) -> JsValue {
150 let json = match into_serde_json(&js_value) {
151 Ok(json) => json,
152 Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))),
153 };
154
155 match jsonpath::select(&json, path) {
156 Ok(ret) => match JsValue::from_serde(&ret) {
157 Ok(ret) => ret,
158 Err(e) => JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string()))),
159 },
160 Err(e) => JsValue::from_str(&format!("{:?}", e)),
161 }
162 }
163
164 #[wasm_bindgen(catch, js_name = "deleteValue")]
delete(js_value: JsValue, path: &str) -> JsValue165 pub fn delete(js_value: JsValue, path: &str) -> JsValue {
166 let json = match into_serde_json(&js_value) {
167 Ok(json) => json,
168 Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))),
169 };
170
171 match jsonpath::delete(json, path) {
172 Ok(ret) => match JsValue::from_serde(&ret) {
173 Ok(ret) => ret,
174 Err(e) => JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string()))),
175 },
176 Err(e) => JsValue::from_str(&format!("{:?}", e)),
177 }
178 }
179
180 #[wasm_bindgen(catch, js_name = "replaceWith")]
replace_with(js_value: JsValue, path: &str, fun: js_sys::Function) -> JsValue181 pub fn replace_with(js_value: JsValue, path: &str, fun: js_sys::Function) -> JsValue {
182 let json = match into_serde_json(&js_value) {
183 Ok(json) => json,
184 Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))),
185 };
186
187 match jsonpath::replace_with(json, path, &mut |v| replace_fun(v, &fun)) {
188 Ok(ret) => match JsValue::from_serde(&ret) {
189 Ok(ret) => ret,
190 Err(e) => JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string()))),
191 },
192 Err(e) => JsValue::from_str(&format!("{:?}", e)),
193 }
194 }
195
196 ///
197 /// `wasm_bindgen` 제약으로 builder-pattern을 구사 할 수 없다.
198 /// lifetime 제약으로 Selector를 사용 할 수 없다.
199 ///
200 #[wasm_bindgen]
201 #[derive(Default)]
202 pub struct Selector {
203 path: Option<String>,
204 value: Option<Value>,
205 }
206
207 #[wasm_bindgen]
208 impl Selector {
209 #[wasm_bindgen(constructor)]
new() -> Self210 pub fn new() -> Self {
211 Selector::default()
212 }
213
214 #[wasm_bindgen(catch)]
path(&mut self, path: &str) -> Result<(), JsValue>215 pub fn path(&mut self, path: &str) -> Result<(), JsValue> {
216 self.path = Some(path.to_string());
217 Ok(())
218 }
219
220 #[wasm_bindgen(catch)]
value(&mut self, value: JsValue) -> Result<(), JsValue>221 pub fn value(&mut self, value: JsValue) -> Result<(), JsValue> {
222 let json = into_serde_json(&value)
223 .map_err(|e| JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))))?;
224 self.value = Some(json);
225 Ok(())
226 }
227
228 #[wasm_bindgen(catch, js_name = select)]
select(&mut self) -> Result<JsValue, JsValue>229 pub fn select(&mut self) -> Result<JsValue, JsValue> {
230 let mut selector = _Selector::new();
231
232 if let Some(path) = &self.path {
233 let _ = selector
234 .str_path(&path)
235 .map_err(|e| JsValue::from_str(&format!("{:?}", e)))?;
236 } else {
237 return Err(JsValue::from_str(&format!(
238 "{:?}",
239 JsonPathError::EmptyPath
240 )));
241 }
242
243 if let Some(value) = &self.value {
244 let _ = selector.value(value);
245 } else {
246 return Err(JsValue::from_str(&format!(
247 "{:?}",
248 JsonPathError::EmptyValue
249 )));
250 }
251
252 match selector.select() {
253 Ok(ret) => match JsValue::from_serde(&ret) {
254 Ok(ret) => Ok(ret),
255 Err(e) => Err(JsValue::from_str(&format!(
256 "{:?}",
257 JsonPathError::Serde(e.to_string())
258 ))),
259 },
260 Err(e) => Err(JsValue::from_str(&format!("{:?}", e))),
261 }
262 }
263 }
264
265 ///
266 /// `wasm_bindgen` 제약으로 builder-pattern을 구사 할 수 없다.
267 ///
268 #[wasm_bindgen]
269 #[derive(Default)]
270 pub struct SelectorMut {
271 path: Option<String>,
272 value: Option<Value>,
273 }
274
275 #[wasm_bindgen]
276 impl SelectorMut {
277 #[wasm_bindgen(constructor)]
new() -> Self278 pub fn new() -> Self {
279 SelectorMut::default()
280 }
281
282 #[wasm_bindgen(catch)]
path(&mut self, path: &str) -> Result<(), JsValue>283 pub fn path(&mut self, path: &str) -> Result<(), JsValue> {
284 self.path = Some(path.to_string());
285 Ok(())
286 }
287
288 #[wasm_bindgen(catch)]
value(&mut self, value: JsValue) -> Result<(), JsValue>289 pub fn value(&mut self, value: JsValue) -> Result<(), JsValue> {
290 let json = into_serde_json(&value)
291 .map_err(|e| JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))))?;
292 self.value = Some(json);
293 Ok(())
294 }
295
296 #[wasm_bindgen(catch, js_name = "deleteValue")]
delete(&mut self) -> Result<(), JsValue>297 pub fn delete(&mut self) -> Result<(), JsValue> {
298 let mut selector = _SelectorMut::new();
299
300 if let Some(path) = &self.path {
301 let _ = selector.str_path(path);
302 } else {
303 return Err(JsValue::from_str(&format!(
304 "{:?}",
305 JsonPathError::EmptyPath
306 )));
307 };
308
309 if let Some(value) = self.value.take() {
310 selector.value(value);
311 } else {
312 return Err(JsValue::from_str(&format!(
313 "{:?}",
314 JsonPathError::EmptyValue
315 )));
316 };
317
318 match selector.delete() {
319 Err(e) => Err(JsValue::from_str(&format!("{:?}", e))),
320 _ => {
321 self.value = selector.take();
322 Ok(())
323 }
324 }
325 }
326
327 #[wasm_bindgen(catch, js_name = replaceWith)]
replace_with(&mut self, fun: js_sys::Function) -> Result<(), JsValue>328 pub fn replace_with(&mut self, fun: js_sys::Function) -> Result<(), JsValue> {
329 let mut selector = _SelectorMut::new();
330
331 if let Some(path) = &self.path {
332 let _ = selector.str_path(path);
333 } else {
334 return Err(JsValue::from_str(&format!(
335 "{:?}",
336 JsonPathError::EmptyPath
337 )));
338 };
339
340 if let Some(value) = self.value.take() {
341 selector.value(value);
342 } else {
343 return Err(JsValue::from_str(&format!(
344 "{:?}",
345 JsonPathError::EmptyValue
346 )));
347 };
348
349 match selector.replace_with(&mut |v| replace_fun(v, &fun)) {
350 Err(e) => Err(JsValue::from_str(&format!("{:?}", e))),
351 _ => {
352 self.value = selector.take();
353 Ok(())
354 }
355 }
356 }
357
358 #[wasm_bindgen(catch)]
take(&mut self) -> Result<JsValue, JsValue>359 pub fn take(&mut self) -> Result<JsValue, JsValue> {
360 match self.value.take() {
361 Some(ret) => match JsValue::from_serde(&ret) {
362 Ok(ret) => Ok(ret),
363 Err(e) => Err(JsValue::from_str(&format!("{:?}", e))),
364 },
365 None => Err(JsValue::from_str(&format!(
366 "{:?}",
367 JsonPathError::EmptyValue
368 ))),
369 }
370 }
371 }
372