1 mod bindings {
2 wit_bindgen::generate!({
3 path: "../misc/component-async-tests/wit",
4 world: "synchronous-transmit-guest",
5 });
6 }
7
8 use {
9 std::mem,
10 test_programs::async_::{
11 CALLBACK_CODE_EXIT, CALLBACK_CODE_YIELD, COMPLETED, DROPPED, EVENT_NONE, context_get,
12 context_set,
13 },
14 };
15
16 #[cfg(target_arch = "wasm32")]
17 #[link(wasm_import_module = "[export]local:local/synchronous-transmit")]
18 unsafe extern "C" {
19 #[link_name = "[task-return]start"]
task_return_start(_: u32, _: *const u8, _: usize, _: u32, _: u8)20 fn task_return_start(_: u32, _: *const u8, _: usize, _: u32, _: u8);
21 }
22 #[cfg(not(target_arch = "wasm32"))]
task_return_start(_: u32, _: *const u8, _: usize, _: u32, _: u8)23 unsafe extern "C" fn task_return_start(_: u32, _: *const u8, _: usize, _: u32, _: u8) {
24 unreachable!()
25 }
26
27 #[cfg(target_arch = "wasm32")]
28 #[link(wasm_import_module = "[export]local:local/synchronous-transmit")]
29 unsafe extern "C" {
30 #[link_name = "[stream-new-0]start"]
stream_new() -> u6431 fn stream_new() -> u64;
32 }
33 #[cfg(not(target_arch = "wasm32"))]
stream_new() -> u6434 unsafe extern "C" fn stream_new() -> u64 {
35 unreachable!()
36 }
37
38 #[cfg(target_arch = "wasm32")]
39 #[link(wasm_import_module = "[export]local:local/synchronous-transmit")]
40 unsafe extern "C" {
41 #[link_name = "[stream-write-0]start"]
stream_write(_: u32, _: *const u8, _: usize) -> u3242 fn stream_write(_: u32, _: *const u8, _: usize) -> u32;
43 }
44 #[cfg(not(target_arch = "wasm32"))]
stream_write(_: u32, _: *const u8, _: usize) -> u3245 unsafe extern "C" fn stream_write(_: u32, _: *const u8, _: usize) -> u32 {
46 unreachable!()
47 }
48
49 #[cfg(target_arch = "wasm32")]
50 #[link(wasm_import_module = "[export]local:local/synchronous-transmit")]
51 unsafe extern "C" {
52 #[link_name = "[stream-read-0]start"]
stream_read(_: u32, _: *mut u8, _: usize) -> u3253 fn stream_read(_: u32, _: *mut u8, _: usize) -> u32;
54 }
55 #[cfg(not(target_arch = "wasm32"))]
stream_read(_: u32, _: *mut u8, _: usize) -> u3256 unsafe extern "C" fn stream_read(_: u32, _: *mut u8, _: usize) -> u32 {
57 unreachable!()
58 }
59
60 #[cfg(target_arch = "wasm32")]
61 #[link(wasm_import_module = "[export]local:local/synchronous-transmit")]
62 unsafe extern "C" {
63 #[link_name = "[stream-drop-readable-0]start"]
stream_drop_readable(_: u32)64 fn stream_drop_readable(_: u32);
65 }
66 #[cfg(not(target_arch = "wasm32"))]
stream_drop_readable(_: u32)67 unsafe extern "C" fn stream_drop_readable(_: u32) {
68 unreachable!()
69 }
70
71 #[cfg(target_arch = "wasm32")]
72 #[link(wasm_import_module = "[export]local:local/synchronous-transmit")]
73 unsafe extern "C" {
74 #[link_name = "[stream-drop-writable-0]start"]
stream_drop_writable(_: u32)75 fn stream_drop_writable(_: u32);
76 }
77 #[cfg(not(target_arch = "wasm32"))]
stream_drop_writable(_: u32)78 unsafe extern "C" fn stream_drop_writable(_: u32) {
79 unreachable!()
80 }
81
82 #[cfg(target_arch = "wasm32")]
83 #[link(wasm_import_module = "[export]local:local/synchronous-transmit")]
84 unsafe extern "C" {
85 #[link_name = "[future-new-1]start"]
future_new() -> u6486 fn future_new() -> u64;
87 }
88 #[cfg(not(target_arch = "wasm32"))]
future_new() -> u6489 unsafe extern "C" fn future_new() -> u64 {
90 unreachable!()
91 }
92
93 #[cfg(target_arch = "wasm32")]
94 #[link(wasm_import_module = "[export]local:local/synchronous-transmit")]
95 unsafe extern "C" {
96 #[link_name = "[future-write-1]start"]
future_write(_: u32, _: *const u8) -> u3297 fn future_write(_: u32, _: *const u8) -> u32;
98 }
99 #[cfg(not(target_arch = "wasm32"))]
future_write(_: u32, _: *const u8) -> u32100 unsafe extern "C" fn future_write(_: u32, _: *const u8) -> u32 {
101 unreachable!()
102 }
103
104 #[cfg(target_arch = "wasm32")]
105 #[link(wasm_import_module = "[export]local:local/synchronous-transmit")]
106 unsafe extern "C" {
107 #[link_name = "[future-read-1]start"]
future_read(_: u32, _: *mut u8) -> u32108 fn future_read(_: u32, _: *mut u8) -> u32;
109 }
110 #[cfg(not(target_arch = "wasm32"))]
future_read(_: u32, _: *mut u8) -> u32111 unsafe extern "C" fn future_read(_: u32, _: *mut u8) -> u32 {
112 unreachable!()
113 }
114
115 #[cfg(target_arch = "wasm32")]
116 #[link(wasm_import_module = "[export]local:local/synchronous-transmit")]
117 unsafe extern "C" {
118 #[link_name = "[future-drop-readable-1]start"]
future_drop_readable(_: u32)119 fn future_drop_readable(_: u32);
120 }
121 #[cfg(not(target_arch = "wasm32"))]
future_drop_readable(_: u32)122 unsafe extern "C" fn future_drop_readable(_: u32) {
123 unreachable!()
124 }
125
126 #[cfg(target_arch = "wasm32")]
127 #[link(wasm_import_module = "[export]local:local/synchronous-transmit")]
128 unsafe extern "C" {
129 #[link_name = "[future-drop-writable-1]start"]
future_drop_writable(_: u32)130 fn future_drop_writable(_: u32);
131 }
132 #[cfg(not(target_arch = "wasm32"))]
future_drop_writable(_: u32)133 unsafe extern "C" fn future_drop_writable(_: u32) {
134 unreachable!()
135 }
136
137 static STREAM_BYTES_TO_WRITE: &[u8] = &[1, 3, 5, 7, 11];
138 static FUTURE_BYTE_TO_WRITE: u8 = 13;
139
140 enum State {
141 S0 {
142 stream: u32,
143 stream_expected: Vec<u8>,
144 future: u32,
145 future_expected: u8,
146 },
147 S1 {
148 stream_tx: u32,
149 stream: u32,
150 stream_expected: Vec<u8>,
151 future_tx: u32,
152 future: u32,
153 future_expected: u8,
154 },
155 }
156
157 #[unsafe(export_name = "[async-lift]local:local/synchronous-transmit#start")]
export_start( stream: u32, stream_expected: u32, stream_expected_len: u32, future: u32, future_expected: u8, ) -> u32158 unsafe extern "C" fn export_start(
159 stream: u32,
160 stream_expected: u32,
161 stream_expected_len: u32,
162 future: u32,
163 future_expected: u8,
164 ) -> u32 {
165 let stream_expected_len = usize::try_from(stream_expected_len).unwrap();
166
167 unsafe {
168 context_set(
169 u32::try_from(Box::into_raw(Box::new(State::S0 {
170 stream,
171 stream_expected: Vec::from_raw_parts(
172 stream_expected as usize as *mut u8,
173 stream_expected_len,
174 stream_expected_len,
175 ),
176 future,
177 future_expected,
178 })) as usize)
179 .unwrap(),
180 );
181
182 callback_start(EVENT_NONE, 0, 0)
183 }
184 }
185
186 #[unsafe(export_name = "[callback][async-lift]local:local/synchronous-transmit#start")]
callback_start(event0: u32, _event1: u32, _event2: u32) -> u32187 unsafe extern "C" fn callback_start(event0: u32, _event1: u32, _event2: u32) -> u32 {
188 unsafe {
189 let state = &mut *(usize::try_from(context_get()).unwrap() as *mut State);
190 match state {
191 &mut State::S0 {
192 stream,
193 ref mut stream_expected,
194 future,
195 future_expected,
196 } => {
197 assert_eq!(event0, EVENT_NONE);
198
199 let pair = stream_new();
200 let stream_tx = u32::try_from(pair >> 32).unwrap();
201 let stream_rx = u32::try_from(pair & 0xFFFFFFFF_u64).unwrap();
202
203 let pair = future_new();
204 let future_tx = u32::try_from(pair >> 32).unwrap();
205 let future_rx = u32::try_from(pair & 0xFFFFFFFF_u64).unwrap();
206
207 task_return_start(
208 stream_rx,
209 STREAM_BYTES_TO_WRITE.as_ptr(),
210 STREAM_BYTES_TO_WRITE.len(),
211 future_rx,
212 FUTURE_BYTE_TO_WRITE,
213 );
214
215 *state = State::S1 {
216 stream_tx,
217 stream,
218 stream_expected: mem::take(stream_expected),
219 future_tx,
220 future,
221 future_expected,
222 };
223
224 CALLBACK_CODE_YIELD
225 }
226
227 &mut State::S1 {
228 stream_tx,
229 stream,
230 ref mut stream_expected,
231 future_tx,
232 future,
233 future_expected,
234 } => {
235 // Now we synchronously read and write and expect that the
236 // operations complete.
237
238 let mut buffer = vec![0_u8; stream_expected.len()];
239 let status = stream_read(stream, buffer.as_mut_ptr(), stream_expected.len());
240 assert_eq!(
241 status,
242 DROPPED | u32::try_from(stream_expected.len() << 4).unwrap()
243 );
244 assert_eq!(&buffer[..], stream_expected);
245 stream_drop_readable(stream);
246
247 let status = stream_write(
248 stream_tx,
249 STREAM_BYTES_TO_WRITE.as_ptr(),
250 STREAM_BYTES_TO_WRITE.len(),
251 );
252 assert_eq!(
253 status,
254 DROPPED | u32::try_from(STREAM_BYTES_TO_WRITE.len() << 4).unwrap()
255 );
256 stream_drop_writable(stream_tx);
257
258 let received = &mut 0_u8;
259 let status = future_read(future, received);
260 assert_eq!(status, COMPLETED);
261 assert_eq!(*received, future_expected);
262 future_drop_readable(future);
263
264 let status = future_write(future_tx, &FUTURE_BYTE_TO_WRITE);
265 assert_eq!(status, COMPLETED);
266 future_drop_writable(future_tx);
267
268 CALLBACK_CODE_EXIT
269 }
270 }
271 }
272 }
273
274 // Unused function; required since this file is built as a `bin`:
main()275 fn main() {}
276