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