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_POLL, EVENT_NONE, EVENT_SUBTASK, STATUS_RETURNED,
14         context_get, context_set, subtask_drop, waitable_join, waitable_set_drop, waitable_set_new,
15     },
16 };
17 
18 #[cfg(target_arch = "wasm32")]
19 #[link(wasm_import_module = "[export]local:local/run")]
20 unsafe extern "C" {
21     #[link_name = "[task-return]run"]
22     fn task_return_run();
23 }
24 #[cfg(not(target_arch = "wasm32"))]
25 unsafe extern "C" fn task_return_run() {
26     unreachable!()
27 }
28 
29 fn async_when_ready() -> u32 {
30     #[cfg(not(target_arch = "wasm32"))]
31     {
32         unreachable!()
33     }
34 
35     #[cfg(target_arch = "wasm32")]
36     {
37         #[link(wasm_import_module = "local:local/ready")]
38         unsafe extern "C" {
39             #[link_name = "[async-lower]when-ready"]
40             fn call_when_ready() -> u32;
41         }
42         unsafe { call_when_ready() }
43     }
44 }
45 
46 enum State {
47     S0,
48     S1 { set: u32 },
49     S2 { set: u32, call: u32 },
50     S3 { set: u32, call: u32 },
51     S4 { set: u32 },
52     S5 { set: u32 },
53 }
54 
55 #[unsafe(export_name = "[async-lift]local:local/run#run")]
56 unsafe extern "C" fn export_run() -> u32 {
57     context_set(u32::try_from(Box::into_raw(Box::new(State::S0)) as usize).unwrap());
58     callback_run(EVENT_NONE, 0, 0)
59 }
60 
61 #[unsafe(export_name = "[callback][async-lift]local:local/run#run")]
62 unsafe extern "C" fn callback_run(event0: u32, event1: u32, event2: u32) -> u32 {
63     let state = &mut *(usize::try_from(context_get()).unwrap() as *mut State);
64     match state {
65         State::S0 => {
66             assert_eq!(event0, EVENT_NONE);
67 
68             ready::set_ready(false);
69 
70             let set = waitable_set_new();
71 
72             *state = State::S1 { set };
73 
74             CALLBACK_CODE_POLL | (set << 4)
75         }
76 
77         State::S1 { set } => {
78             assert_eq!(event0, EVENT_NONE);
79 
80             let set = *set;
81             let result = async_when_ready();
82             let status = result & 0xf;
83             let call = result >> 4;
84             assert!(status != STATUS_RETURNED);
85             waitable_join(call, set);
86 
87             *state = State::S2 { set, call };
88 
89             CALLBACK_CODE_POLL | (set << 4)
90         }
91 
92         State::S2 { set, call } => {
93             assert_eq!(event0, EVENT_NONE);
94 
95             let set = *set;
96             let call = *call;
97             ready::set_ready(true);
98 
99             *state = State::S3 { set, call };
100 
101             CALLBACK_CODE_POLL | (set << 4)
102         }
103 
104         State::S3 { set, call } => {
105             let set = *set;
106 
107             if event0 != EVENT_NONE {
108                 assert_eq!(event0, EVENT_SUBTASK);
109                 assert_eq!(event1, *call);
110                 assert_eq!(event2, STATUS_RETURNED);
111 
112                 subtask_drop(*call);
113 
114                 *state = State::S4 { set };
115             }
116 
117             CALLBACK_CODE_POLL | (set << 4)
118         }
119 
120         State::S4 { set } => {
121             assert_eq!(event0, EVENT_NONE);
122 
123             let set = *set;
124             assert_eq!(async_when_ready(), STATUS_RETURNED);
125 
126             *state = State::S5 { set };
127 
128             CALLBACK_CODE_POLL | (set << 4)
129         }
130 
131         State::S5 { set } => {
132             assert_eq!(event0, EVENT_NONE);
133 
134             waitable_set_drop(*set);
135 
136             drop(Box::from_raw(state));
137 
138             context_set(0);
139 
140             task_return_run();
141 
142             CALLBACK_CODE_EXIT
143         }
144     }
145 }
146 
147 // Unused function; required since this file is built as a `bin`:
148 fn main() {}
149