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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! Javascript endpoints rendered from service traits at compile time.
//!
//! [`endpoint!`](macro@endpoint) is the Javascript counterpart of [`crate::Builder`] and reads
//! the same way: `service =` names the trait the generated endpoint **serves**, `client =` the
//! trait it **calls**, and the values are the same generated struct names one would pass to
//! [`with_service`](crate::Builder::with_service) and
//! [`with_client`](crate::Builder::with_client). At least one is required.
//!
//! ```rust,ignore
//! // The Rust side of this binary.
//! Builder::new(iface)
//! .with_service::<CalculatorService<_>>(calculator)
//! .with_client::<DisplayClient>();
//! // The other end of the same connection, described as itself.
//! web_rpc::js::endpoint!(service = DisplayService, client = CalculatorClient);
//! ```
//!
//! The expansion writes a `.mjs` and a `.d.ts` into two custom sections of the wasm binary,
//! named after the class in snake_case: `__web_rpc_calculator_client_js` and
//! `__web_rpc_calculator_client_d_ts` for the example above. Extract them with `llvm-objcopy`
//! (or `rust-objcopy` from `cargo-binutils`), before wasm-bindgen runs:
//!
//! ```text
//! llvm-objcopy --dump-section=__web_rpc_calculator_client_js=calculator_client.mjs \
//! --dump-section=__web_rpc_calculator_client_d_ts=calculator_client.d.ts \
//! in.wasm out.wasm
//! ```
//!
//! Add `--remove-section=...` for each to strip them from what you ship. The `.mjs` has no
//! imports and needs no bundling.
//!
//! The generated module is the shell in `js/endpoint.mjs`, which is trait-independent,
//! followed by data: a schema value per type the traits reach, a method table per trait, and
//! a class whose methods forward to the shell. Encoding and decoding are interpreted from
//! those values by the shell's `Codec`, which the module also exports along with `Writer` and
//! `Reader`, for an embedder that wants to speak postcard itself.
//!
//! One caveat follows from how `#[link_section]` works on wasm: the macro must be invoked in
//! the binary crate that is linked into the wasm module, because a static in an rlib that
//! contributes no symbol to the link is dropped by wasm-ld.
//!
//! # What the renderers reject
//!
//! Rendering happens during const evaluation, which cannot format a panic message, so the
//! compiler's const-eval backtrace is what points at the offending type. An enum whose struct
//! variant has a field named `tag` would collide with the discriminant of the Typescript union
//! that represents it:
//!
//! ```compile_fail
//! #[derive(serde::Serialize, serde::Deserialize, postcard_schema::Schema)]
//! pub enum Bad {
//! Variant { tag: u32 },
//! }
//!
//! #[web_rpc::service]
//! pub trait Uses {
//! fn take(&self, value: Bad);
//! }
//!
//! web_rpc::js::endpoint!(client = UsesClient);
//! ```
//!
//! So would two types that render to the same Typescript name:
//!
//! ```compile_fail
//! #[derive(serde::Serialize, serde::Deserialize, postcard_schema::Schema)]
//! pub struct Alpha { pub x: u32 }
//!
//! #[derive(serde::Serialize, serde::Deserialize, postcard_schema::Schema)]
//! #[serde(rename = "Alpha")]
//! pub struct Beta { pub y: String }
//!
//! #[web_rpc::service]
//! pub trait Uses {
//! fn one(&self, value: Alpha);
//! fn two(&self, value: Beta);
//! }
//!
//! web_rpc::js::endpoint!(client = UsesClient);
//! ```
//!
//! And so would a type named `Request`, `Subscription` or `Endpoint`, which the generated
//! declarations define themselves:
//!
//! ```compile_fail
//! #[derive(serde::Serialize, serde::Deserialize, postcard_schema::Schema)]
//! pub struct Request { pub id: u32 }
//!
//! #[web_rpc::service]
//! pub trait Uses {
//! fn one(&self, value: Request);
//! }
//!
//! web_rpc::js::endpoint!(client = UsesClient);
//! ```
use crate;
pub use MAX_DECLARATIONS;
pub use endpoint;
pub use Output;
/// The trait-independent part of every generated endpoint, emitted ahead of the rendered
/// schemas, method tables and class.
pub const SHELL: &str = include_str!;
/// What the macro renders: a class name and the traits filling each half of the connection.
/// The number of methods of a service that survived cfg evaluation.
pub const
/// The `index`th enabled method of a service. Its position here is its index on the wire.
pub const
/// Render the Javascript module for one endpoint.
///
/// Call once with `CAPACITY = 0` to measure, then again with `CAPACITY` set to the measured
/// length.
pub const
/// Render the Typescript declarations for one endpoint.
///
/// Call once with `CAPACITY = 0` to measure, then again with `CAPACITY` set to the measured
/// length.
pub const