Add JsValue::{from_serde, into_serde}

These functions are activated with the `serde-serialization` feature of the
`wasm-bindgen` crate. When activated they will allow passing any arbitrary value
into JS that implements the `Serialize` trait and receiving any value from JS
using the `Deserialize` trait. The interchange between JS and Rust is JSON.

Closes #96
This commit is contained in:
Alex Crichton
2018-04-26 19:03:46 -07:00
parent acb5eac96a
commit b8895b3a95
5 changed files with 412 additions and 229 deletions

View File

@ -8,6 +8,11 @@
#![feature(use_extern_macros, wasm_import_module, try_reserve, unsize)]
#![no_std]
#[cfg(feature = "serde-serialize")]
extern crate serde;
#[cfg(feature = "serde-serialize")]
extern crate serde_json;
extern crate wasm_bindgen_macro;
use core::cell::UnsafeCell;
@ -112,22 +117,58 @@ impl JsValue {
}
}
// #[doc(hidden)]
// pub unsafe fn __from_idx(idx: u32) -> JsValue {
// JsValue { idx }
// }
//
// #[doc(hidden)]
// pub fn __get_idx(&self) -> u32 {
// self.idx
// }
//
// #[doc(hidden)]
// pub fn __into_idx(self) -> u32 {
// let ret = self.idx;
// mem::forget(self);
// return ret
// }
/// Creates a new `JsValue` from the JSON serialization of the object `t`
/// provided.
///
/// This function will serialize the provided value `t` to a JSON string,
/// send the JSON string to JS, parse it into a JS object, and then return
/// a handle to the JS object. This is unlikely to be super speedy so it's
/// not recommended for large payloads, but it's a nice to have in some
/// situations!
///
/// Usage of this API requires activating the `serde-serialize` feature of
/// the `wasm-bindgen` crate.
///
/// # Errors
///
/// Returns any error encountered when serializing `T` into JSON.
#[cfg(feature = "serde-serialize")]
pub fn from_serde<T>(t: &T) -> serde_json::Result<JsValue>
where T: serde::ser::Serialize + ?Sized,
{
let s = serde_json::to_string(t)?;
unsafe {
Ok(JsValue {
idx: __wbindgen_json_parse(s.as_ptr(), s.len()),
})
}
}
/// Invokes `JSON.stringify` on this value and then parses the resulting
/// JSON into an arbitrary Rust value.
///
/// This function will first call `JSON.stringify` on the `JsValue` itself.
/// The resulting string is then passed into Rust which then parses it as
/// JSON into the resulting value.
///
/// Usage of this API requires activating the `serde-serialize` feature of
/// the `wasm-bindgen` crate.
///
/// # Errors
///
/// Returns any error encountered when parsing the JSON into a `T`.
#[cfg(feature = "serde-serialize")]
pub fn into_serde<T>(&self) -> serde_json::Result<T>
where T: for<'a> serde::de::Deserialize<'a>,
{
unsafe {
let mut ptr = ptr::null_mut();
let len = __wbindgen_json_serialize(self.idx, &mut ptr);
let s = Vec::from_raw_parts(ptr, len, len);
let s = String::from_utf8_unchecked(s);
serde_json::from_str(&s)
}
}
/// Returns the `f64` value of this JS value if it's an instance of a
/// number.
@ -252,18 +293,13 @@ extern {
fn __wbindgen_string_get(idx: u32, len: *mut usize) -> *mut u8;
fn __wbindgen_throw(a: *const u8, b: usize) -> !;
fn __wbindgen_cb_arity0(a: u32, b: u32, c: u32) -> u32;
fn __wbindgen_cb_arity1(a: u32, b: u32, c: u32) -> u32;
fn __wbindgen_cb_arity2(a: u32, b: u32, c: u32) -> u32;
fn __wbindgen_cb_arity3(a: u32, b: u32, c: u32) -> u32;
fn __wbindgen_cb_arity4(a: u32, b: u32, c: u32) -> u32;
fn __wbindgen_cb_arity5(a: u32, b: u32, c: u32) -> u32;
fn __wbindgen_cb_arity6(a: u32, b: u32, c: u32) -> u32;
fn __wbindgen_cb_arity7(a: u32, b: u32, c: u32) -> u32;
fn __wbindgen_cb_drop(idx: u32);
fn __wbindgen_cb_forget(idx: u32);
fn __wbindgen_describe(v: u32);
fn __wbindgen_json_parse(ptr: *const u8, len: usize) -> u32;
fn __wbindgen_json_serialize(idx: u32, ptr: *mut *mut u8) -> usize;
}
impl Clone for JsValue {