1 #![expect(unsafe_op_in_unsafe_fn, reason = "old code, not worth updating yet")]
2 
3 mod bindings {
4     wit_bindgen::generate!({
5         path: "../misc/component-async-tests/wit",
6         world: "poll",
7     });
8 }
9 
10 use {
11     bindings::local::local::ready,
12     test_programs::async_::{
13         CALLBACK_CODE_EXIT, CALLBACK_CODE_YIELD, EVENT_NONE, EVENT_SUBTASK, STATUS_RETURNED,
14         context_get, context_set, subtask_drop, waitable_join, waitable_set_drop, waitable_set_new,
15         waitable_set_poll,
16     },
17 };
18 
19 #[cfg(target_arch = "wasm32")]
20 #[link(wasm_import_module = "[export]local:local/run")]
21 unsafe extern "C" {
22     #[link_name = "[task-return]run"]
23     fn task_return_run();
24 }
25 #[cfg(not(target_arch = "wasm32"))]
26 unsafe extern "C" fn task_return_run() {
27     unreachable!()
28 }
29 
30 fn async_when_ready(handle: u32) -> u32 {
31     #[cfg(not(target_arch = "wasm32"))]
32     {
33         _ = handle;
34         unreachable!()
35     }
36 
37     #[cfg(target_arch = "wasm32")]
38     {
39         #[link(wasm_import_module = "local:local/ready")]
40         unsafe extern "C" {
41             #[link_name = "[async-lower][method]thing.when-ready"]
42             fn call_when_ready(handle: u32) -> u32;
43         }
44         unsafe { call_when_ready(handle) }
45     }
46 }
47 
48 enum State {
49     S0,
50     S1 {
51         thing: Option<ready::Thing>,
52         set: u32,
53     },
54     S2 {
55         thing: Option<ready::Thing>,
56         set: u32,
57         call: u32,
58     },
59     S3 {
60         thing: Option<ready::Thing>,
61         set: u32,
62         call: u32,
63     },
64     S4 {
65         thing: Option<ready::Thing>,
66         set: u32,
67     },
68     S5 {
69         set: u32,
70     },
71 }
72 
73 #[unsafe(export_name = "[async-lift]local:local/run#run")]
74 unsafe extern "C" fn export_run() -> u32 {
75     context_set(u32::try_from(Box::into_raw(Box::new(State::S0)) as usize).unwrap());
76     callback_run(EVENT_NONE, 0, 0)
77 }
78 
79 #[unsafe(export_name = "[callback][async-lift]local:local/run#run")]
80 unsafe extern "C" fn callback_run(event0: u32, _: u32, _: u32) -> u32 {
81     let state = &mut *(usize::try_from(context_get()).unwrap() as *mut State);
82     match state {
83         State::S0 => {
84             assert_eq!(event0, EVENT_NONE);
85 
86             let thing = ready::Thing::new();
87             thing.set_ready(false);
88 
89             let set = waitable_set_new();
90 
91             *state = State::S1 {
92                 thing: Some(thing),
93                 set,
94             };
95 
96             CALLBACK_CODE_YIELD
97         }
98 
99         &mut State::S1 { ref mut thing, set } => {
100             let thing = thing.take().unwrap();
101             let (event0, _, _) = waitable_set_poll(set);
102 
103             assert_eq!(event0, EVENT_NONE);
104 
105             let result = async_when_ready(thing.handle());
106             let status = result & 0xf;
107             let call = result >> 4;
108             assert!(status != STATUS_RETURNED);
109             waitable_join(call, set);
110 
111             *state = State::S2 {
112                 thing: Some(thing),
113                 set,
114                 call,
115             };
116 
117             CALLBACK_CODE_YIELD
118         }
119 
120         &mut State::S2 {
121             ref mut thing,
122             set,
123             call,
124         } => {
125             let thing = thing.take().unwrap();
126             let (event0, _, _) = waitable_set_poll(set);
127 
128             assert_eq!(event0, EVENT_NONE);
129 
130             thing.set_ready(true);
131 
132             *state = State::S3 {
133                 thing: Some(thing),
134                 set,
135                 call,
136             };
137 
138             CALLBACK_CODE_YIELD
139         }
140 
141         &mut State::S3 {
142             ref mut thing,
143             set,
144             call,
145         } => {
146             let (event0, event1, event2) = waitable_set_poll(set);
147 
148             if event0 != EVENT_NONE {
149                 assert_eq!(event0, EVENT_SUBTASK);
150                 assert_eq!(event1, call);
151                 assert_eq!(event2, STATUS_RETURNED);
152 
153                 subtask_drop(call);
154 
155                 *state = State::S4 {
156                     thing: thing.take(),
157                     set,
158                 };
159             }
160 
161             CALLBACK_CODE_YIELD
162         }
163 
164         &mut State::S4 { ref mut thing, set } => {
165             let thing = thing.take().unwrap();
166             let (event0, _, _) = waitable_set_poll(set);
167 
168             assert_eq!(event0, EVENT_NONE);
169 
170             assert_eq!(async_when_ready(thing.handle()), STATUS_RETURNED);
171 
172             *state = State::S5 { set };
173 
174             CALLBACK_CODE_YIELD
175         }
176 
177         &mut State::S5 { set } => {
178             let (event0, _, _) = waitable_set_poll(set);
179 
180             assert_eq!(event0, EVENT_NONE);
181 
182             waitable_set_drop(set);
183 
184             drop(Box::from_raw(state));
185 
186             context_set(0);
187 
188             task_return_run();
189 
190             CALLBACK_CODE_EXIT
191         }
192     }
193 }
194 
195 // Unused function; required since this file is built as a `bin`:
196 fn main() {}
197