Skip to content

Commit ff13de2

Browse files
committed
Address the feedback
1 parent 86b533e commit ff13de2

File tree

11 files changed

+143
-96
lines changed

11 files changed

+143
-96
lines changed

crates/console/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ categories = ["api-bindings", "development-tools::profiling", "wasm"]
1515
wasm-bindgen = "0.2"
1616
js-sys = "0.3"
1717
serde = { version = "1", features = ["derive"] }
18-
gloo-utils = { version = "0.1", path = "../utils", features = ["serde-serialize"] }
18+
gloo-utils = { version = "0.1", path = "../utils", features = ["serde"] }
1919
[dependencies.web-sys]
2020
version = "0.3"
2121
features = [

crates/console/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub use timer::Timer;
3030

3131
#[doc(hidden)]
3232
pub mod __macro {
33+
use gloo_utils::format::JsValueSerdeExt;
3334
pub use js_sys::Array;
3435
pub use wasm_bindgen::JsValue;
3536
use wasm_bindgen::UnwrapThrowExt;
@@ -38,7 +39,7 @@ pub mod __macro {
3839
data: impl serde::Serialize,
3940
columns: impl IntoIterator<Item = &'a str>,
4041
) {
41-
let data = gloo_utils::json::from_serde(&data).unwrap_throw();
42+
let data = <JsValue as JsValueSerdeExt>::from_serde(&data).unwrap_throw();
4243
let columns = columns.into_iter().map(JsValue::from_str).collect();
4344

4445
crate::externs::table_with_data_and_columns(data, columns);

crates/net/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ rustdoc-args = ["--cfg", "docsrs"]
1818
wasm-bindgen = "0.2"
1919
web-sys = "0.3"
2020
js-sys = "0.3"
21-
gloo-utils = { version = "0.1", path = "../utils", features = ["serde-serialize"] }
21+
gloo-utils = { version = "0.1", path = "../utils", features = ["serde"] }
2222

2323
wasm-bindgen-futures = "0.4"
2424
futures-core = { version = "0.3", optional = true }

crates/net/src/http/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ use wasm_bindgen_futures::JsFuture;
2727
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
2828
use serde::de::DeserializeOwned;
2929

30+
#[cfg(feature = "json")]
31+
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
32+
use gloo_utils::format::JsValueSerdeExt;
33+
3034
pub use headers::Headers;
3135
pub use query::QueryParams;
3236
pub use web_sys::{
@@ -392,7 +396,7 @@ impl Response {
392396
pub async fn json<T: DeserializeOwned>(&self) -> Result<T, Error> {
393397
let promise = self.response.json().map_err(js_to_error)?;
394398
let json = JsFuture::from(promise).await.map_err(js_to_error)?;
395-
Ok(gloo_utils::json::into_serde(&json)?)
399+
Ok(JsValueSerdeExt::into_serde(&json)?)
396400
}
397401

398402
/// Reads the response as a String.

crates/net/src/websocket/futures.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use futures_channel::mpsc;
3333
use futures_core::{ready, Stream};
3434
use futures_sink::Sink;
3535
use gloo_utils::errors::JsError;
36+
use gloo_utils::format::JsValueSerdeExt;
3637
use pin_project::{pin_project, pinned_drop};
3738
use std::cell::RefCell;
3839
use std::pin::Pin;
@@ -106,7 +107,7 @@ impl WebSocket {
106107
url: &str,
107108
protocols: &[S],
108109
) -> Result<Self, JsError> {
109-
let json = gloo_utils::json::from_serde(protocols).map_err(|err| {
110+
let json = <JsValue as JsValueSerdeExt>::from_serde(protocols).map_err(|err| {
110111
js_sys::Error::new(&format!(
111112
"Failed to convert protocols to Javascript value: {}",
112113
err

crates/utils/Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,13 @@ features = [
3030
]
3131

3232
[features]
33-
default = ["serde-serialize"]
34-
serde-serialize = ["dep:serde", "dep:serde_json"]
33+
default = ["serde"]
34+
serde = ["dep:serde", "dep:serde_json"]
3535

3636
[dev-dependencies]
3737
wasm-bindgen-test = "0.3"
3838
serde_derive = "1.0"
39+
40+
[package.metadata.docs.rs]
41+
all-features = true
42+
rustdoc-args = ["--cfg", "docsrs"]

crates/utils/src/format/json.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#![cfg(feature = "serde")]
2+
3+
use wasm_bindgen::{JsValue, UnwrapThrowExt};
4+
mod private {
5+
pub trait Sealed {}
6+
impl Sealed for wasm_bindgen::JsValue {}
7+
}
8+
9+
/// Extenstion trait to provide conversion between [`JsValue`](wasm_bindgen::JsValue) and [`serde`].
10+
///
11+
/// Usage of this API requires activating the `serde` feature of the `gloo-utils` crate.
12+
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
13+
pub trait JsValueSerdeExt: private::Sealed {
14+
/// Creates a new `JsValue` from the JSON serialization of the object `t`
15+
/// provided.
16+
///
17+
/// This function will serialize the provided value `t` to a JSON string,
18+
/// send the JSON string to JS, parse it into a JS object, and then return
19+
/// a handle to the JS object. This is unlikely to be super speedy so it's
20+
/// not recommended for large payloads, but it's a nice to have in some
21+
/// situations!
22+
///
23+
/// Usage of this API requires activating the `serde` feature of
24+
/// the `gloo-utils` crate.
25+
///
26+
/// # Errors
27+
///
28+
/// Returns any error encountered when serializing `T` into JSON.
29+
///
30+
/// # Panics
31+
///
32+
/// Panics if [`serde_json`](serde_json::to_string) generated JSON that couldn't be parsed by [`js_sys`].
33+
/// Uses [`unwrap_throw`](UnwrapThrowExt::unwrap_throw) from [`wasm_bindgen::UnwrapThrowExt`].
34+
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
35+
fn from_serde<T>(t: &T) -> serde_json::Result<JsValue>
36+
where
37+
T: serde::ser::Serialize + ?Sized;
38+
39+
/// Invokes `JSON.stringify` on this value and then parses the resulting
40+
/// JSON into an arbitrary Rust value.
41+
///
42+
/// This function will first call `JSON.stringify` on the `JsValue` itself.
43+
/// The resulting string is then passed into Rust which then parses it as
44+
/// JSON into the resulting value.
45+
///
46+
/// Usage of this API requires activating the `serde` feature of
47+
/// the `gloo-utils` crate.
48+
///
49+
/// # Errors
50+
///
51+
/// Returns any error encountered when parsing the JSON into a `T`.
52+
///
53+
/// # Panics
54+
///
55+
/// Panics if [`js_sys`] couldn't stringify the JsValue. Uses [`unwrap_throw`](UnwrapThrowExt::unwrap_throw)
56+
/// from [`wasm_bindgen::UnwrapThrowExt`].
57+
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
58+
#[allow(clippy::wrong_self_convention)]
59+
fn into_serde<T>(&self) -> serde_json::Result<T>
60+
where
61+
T: for<'a> serde::de::Deserialize<'a>;
62+
}
63+
64+
impl JsValueSerdeExt for JsValue {
65+
fn from_serde<T>(t: &T) -> serde_json::Result<JsValue>
66+
where
67+
T: serde::ser::Serialize + ?Sized,
68+
{
69+
let s = serde_json::to_string(t)?;
70+
Ok(js_sys::JSON::parse(&s).unwrap_throw())
71+
}
72+
73+
fn into_serde<T>(&self) -> serde_json::Result<T>
74+
where
75+
T: for<'a> serde::de::Deserialize<'a>,
76+
{
77+
let s = if self.is_undefined() {
78+
String::new()
79+
} else {
80+
js_sys::JSON::stringify(self)
81+
.map(String::from)
82+
.unwrap_throw()
83+
};
84+
serde_json::from_str(&s)
85+
}
86+
}

crates/utils/src/json.rs

Lines changed: 0 additions & 63 deletions
This file was deleted.

crates/utils/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
#![cfg_attr(docsrs, feature(doc_cfg))]
2+
13
pub mod errors;
24
pub mod iter;
3-
pub mod json;
5+
pub mod format {
6+
mod json;
7+
pub use json::JsValueSerdeExt;
8+
}
49
use wasm_bindgen::UnwrapThrowExt;
510

611
/// Convenience function to avoid repeating expect logic.

crates/utils/tests/serde.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ exports.verify_serde = function(a) {
88
c: null,
99
d: { a: 1 }
1010
});
11+
};
1112

13+
exports.make_js_value = function() {
1214
return {
1315
a: 2,
1416
b: 'bar',

crates/utils/tests/serde.rs

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
#![cfg(target_arch = "wasm32")]
2-
2+
#![cfg(feature = "serde")]
33
extern crate wasm_bindgen;
44
extern crate wasm_bindgen_test;
55

66
use wasm_bindgen::prelude::*;
77
use wasm_bindgen_test::*;
88

9-
use gloo_utils::json::{from_serde, into_serde};
9+
use gloo_utils::format::JsValueSerdeExt;
10+
1011
use serde_derive::{Deserialize, Serialize};
1112

1213
#[wasm_bindgen(start)]
@@ -16,44 +17,50 @@ pub fn start() {
1617

1718
#[wasm_bindgen(module = "/tests/serde.js")]
1819
extern "C" {
19-
fn verify_serde(val: JsValue) -> JsValue;
20+
fn verify_serde(val: JsValue);
21+
fn make_js_value() -> JsValue;
22+
}
23+
24+
#[derive(Deserialize, Serialize, Debug)]
25+
pub struct SerdeFoo {
26+
a: u32,
27+
b: String,
28+
c: Option<SerdeBar>,
29+
d: SerdeBar,
30+
}
31+
32+
#[derive(Deserialize, Serialize, Debug)]
33+
pub struct SerdeBar {
34+
a: u32,
2035
}
2136

22-
#[cfg(feature = "serde-serialize")]
2337
#[wasm_bindgen_test]
24-
fn it_works() {
25-
#[derive(Deserialize, Serialize, Debug)]
26-
pub struct SerdeFoo {
27-
a: u32,
28-
b: String,
29-
c: Option<SerdeBar>,
30-
d: SerdeBar,
31-
}
32-
33-
#[derive(Deserialize, Serialize, Debug)]
34-
pub struct SerdeBar {
35-
a: u32,
36-
}
37-
38-
let js = from_serde("foo").unwrap();
38+
fn from_serde() {
39+
let js = JsValue::from_serde("foo").unwrap();
3940
assert_eq!(js.as_string(), Some("foo".to_string()));
4041

41-
let ret = verify_serde(
42-
from_serde(&SerdeFoo {
42+
verify_serde(
43+
JsValue::from_serde(&SerdeFoo {
4344
a: 0,
4445
b: "foo".to_string(),
4546
c: None,
4647
d: SerdeBar { a: 1 },
4748
})
4849
.unwrap(),
4950
);
50-
let foo = into_serde::<SerdeFoo>(&ret).unwrap();
51+
}
52+
53+
#[wasm_bindgen_test]
54+
fn into_serde() {
55+
let js_value = make_js_value();
56+
let foo = js_value.into_serde::<SerdeFoo>().unwrap();
5157
assert_eq!(foo.a, 2);
5258
assert_eq!(foo.b, "bar");
5359
assert!(foo.c.is_some());
5460
assert_eq!(foo.c.as_ref().unwrap().a, 3);
5561
assert_eq!(foo.d.a, 4);
56-
assert_eq!(into_serde::<String>(&JsValue::from("bar")).unwrap(), "bar");
57-
assert_eq!(into_serde::<i32>(&JsValue::undefined()).ok(), None);
58-
assert_eq!(into_serde::<i32>(&JsValue::null()).ok(), None);
62+
63+
assert_eq!(JsValue::from("bar").into_serde::<String>().unwrap(), "bar");
64+
assert_eq!(JsValue::undefined().into_serde::<i32>().ok(), None);
65+
assert_eq!(JsValue::null().into_serde::<i32>().ok(), None);
5966
}

0 commit comments

Comments
 (0)