1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//! Explicit routing wrappers.
//!
//! A value in an RPC signature crosses the channel either as postcard bytes inside the
//! payload, or as a Javascript value in the message array. The wrapper picks the route:
//! [`Post`] and [`Transfer`] take the Javascript path, everything else is postcard-encoded
//! and must implement [`postcard_schema::Schema`].
//!
//! [`Transfer`] additionally puts the value on the `postMessage` transfer list, so it moves
//! rather than being copied by the structured clone algorithm.
//!
//! No trait constrains what may be transferred. `T` must be a transferable object as defined
//! by the structured clone algorithm (`ArrayBuffer`, `MessagePort`, `OffscreenCanvas`,
//! `ImageBitmap`, the stream types, ...); anything else is a `DataCloneError` thrown by the
//! browser at the moment of sending. A typed array is not transferable: send
//! `Transfer<ArrayBuffer>` and rebuild the view on the other side. A view over wasm linear
//! memory can never be transferred, so [`Post`] it instead.
//!
//! A bare Javascript type in a signature does not compile:
//!
//! ```compile_fail
//! #[web_rpc::service]
//! pub trait Echo {
//! fn echo(&self, value: js_sys::JsString) -> js_sys::JsString;
//! }
//! ```
//!
//! A payload type without `#[derive(Schema)]` is rejected at the argument that uses it:
//!
//! ```compile_fail
//! #[derive(serde::Serialize, serde::Deserialize)]
//! pub struct Point { x: u32 }
//!
//! #[web_rpc::service]
//! pub trait Plot {
//! fn plot(&self, point: Point);
//! }
//! ```
use Deref;
use JsCast;
/// Wrapper that routes `T` across the channel as a Javascript value.
///
/// ```rust
/// # use web_rpc::wrap::Post;
/// #[web_rpc::service]
/// pub trait Echo {
/// fn echo(&self, value: Post<js_sys::JsString>) -> Post<js_sys::JsString>;
/// }
/// ```
;
/// Wrapper that routes `T` across the channel as a Javascript value and puts it on the
/// transfer list, moving it out of the sending context.
///
/// ```rust
/// # use web_rpc::wrap::Transfer;
/// #[web_rpc::service]
/// pub trait Upload {
/// fn upload(&self, buffer: Transfer<js_sys::ArrayBuffer>) -> u32;
/// }
/// ```
;
impl_wrapper!;
impl_wrapper!;
/// Borrow a Javascript value as a [`JsValue`](wasm_bindgen::JsValue).
///
/// The `js_sys` and `web_sys` types implement `AsRef` for their whole prototype chain; this
/// selects the `JsValue` impl.