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"] 20 fn task_return_start(_: u32, _: *const u8, _: usize, _: u32, _: u8); 21 } 22 #[cfg(not(target_arch = "wasm32"))] 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"] 31 fn stream_new() -> u64; 32 } 33 #[cfg(not(target_arch = "wasm32"))] 34 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"] 42 fn stream_write(_: u32, _: *const u8, _: usize) -> u32; 43 } 44 #[cfg(not(target_arch = "wasm32"))] 45 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"] 53 fn stream_read(_: u32, _: *mut u8, _: usize) -> u32; 54 } 55 #[cfg(not(target_arch = "wasm32"))] 56 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"] 64 fn stream_drop_readable(_: u32); 65 } 66 #[cfg(not(target_arch = "wasm32"))] 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"] 75 fn stream_drop_writable(_: u32); 76 } 77 #[cfg(not(target_arch = "wasm32"))] 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"] 86 fn future_new() -> u64; 87 } 88 #[cfg(not(target_arch = "wasm32"))] 89 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"] 97 fn future_write(_: u32, _: *const u8) -> u32; 98 } 99 #[cfg(not(target_arch = "wasm32"))] 100 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"] 108 fn future_read(_: u32, _: *mut u8) -> u32; 109 } 110 #[cfg(not(target_arch = "wasm32"))] 111 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"] 119 fn future_drop_readable(_: u32); 120 } 121 #[cfg(not(target_arch = "wasm32"))] 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"] 130 fn future_drop_writable(_: u32); 131 } 132 #[cfg(not(target_arch = "wasm32"))] 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")] 158 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")] 187 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`: 275 fn main() {} 276