assemblylift_core_io_guest/
lib.rs1use std::future::Future;
2use std::io::BufReader;
3use std::marker::PhantomData;
4use std::pin::Pin;
5use std::task::{Context, Poll, Waker};
6
7use serde::{Deserialize, de::DeserializeOwned};
8
9use assemblylift_core_io_common::constants::{FUNCTION_INPUT_BUFFER_SIZE, IO_BUFFER_SIZE_BYTES};
10
11extern "C" {
12 fn __asml_abi_io_poll(id: u32) -> i32;
14 fn __asml_abi_io_len(id: u32) -> u32;
15 fn __asml_abi_io_load(id: u32) -> i32;
16 fn __asml_abi_io_next() -> i32;
17
18 fn __asml_abi_clock_time_get() -> u64;
20
21 fn __asml_abi_console_log(ptr: *const u8, len: usize);
23
24 fn __asml_abi_input_start() -> i32;
26 fn __asml_abi_input_next() -> i32;
27 fn __asml_abi_input_length_get() -> u64;
28
29 fn __asml_expabi_z85_encode(ptr: *const u8, len: usize, out_ptr: *const u8) -> i32;
31 fn __asml_expabi_z85_decode(ptr: *const u8, len: usize, out_ptr: *const u8) -> i32;
32}
33
34pub static mut IO_BUFFER: [u8; IO_BUFFER_SIZE_BYTES] = [0; IO_BUFFER_SIZE_BYTES];
36
37#[no_mangle]
38pub fn __asml_guest_get_io_buffer_pointer() -> *const u8 {
39 unsafe { IO_BUFFER.as_ptr() }
40}
41
42fn console_log(message: String) {
43 unsafe { __asml_abi_console_log(message.as_ptr(), message.len()) }
44}
45
46pub fn get_time() -> u64 {
47 unsafe { __asml_abi_clock_time_get() }
48}
49
50pub struct IoDocument {
51 bytes_read: usize,
52 pages_read: usize,
53 length: usize,
54}
55
56impl IoDocument {
57 pub fn new(ioid: u32) -> Self {
58 unsafe { __asml_abi_io_load(ioid) };
59 Self {
60 bytes_read: 0,
61 pages_read: 0,
62 length: unsafe { __asml_abi_io_len(ioid) } as usize,
63 }
64 }
65
66 pub fn len(&self) -> usize {
67 self.length
68 }
69}
70
71impl std::io::Read for IoDocument {
72 fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
73 let mut bytes_read = 0usize;
74 if self.bytes_read < self.length {
75 for idx in 0..std::cmp::min(self.length, buf.len()) {
76 buf[idx] = unsafe {
79 IO_BUFFER[self.bytes_read % IO_BUFFER_SIZE_BYTES]
80 };
81 bytes_read += 1;
82 self.bytes_read += 1;
83 if self.bytes_read % IO_BUFFER_SIZE_BYTES == 0 {
84 unsafe { __asml_abi_io_next() };
85 self.pages_read += 1;
86 }
87 }
88 }
89 Ok(bytes_read)
90 }
91}
92
93#[derive(Clone)]
94pub struct Io<'a, R> {
95 pub id: u32,
96 waker: Box<Option<Waker>>,
97 _phantom: PhantomData<&'a R>,
98}
99
100impl<'a, R: Deserialize<'a>> Io<'_, R> {
101 pub fn new(id: u32) -> Self {
102 Io {
103 id,
104 waker: Box::new(None),
105 _phantom: PhantomData,
106 }
107 }
108}
109
110impl<'a, R> Future for Io<'_, R>
111where
112 R: DeserializeOwned,
113{
114 type Output = R;
115
116 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
117 match unsafe { __asml_abi_io_poll(self.id) } {
118 1 => Poll::Ready(read_response::<Self::Output>(self.id).unwrap()),
119 _ => {
120 self.waker = Box::new(Some(cx.waker().clone()));
121 Poll::Pending
122 }
123 }
124 }
125}
126
127fn read_response<'a, T>(id: u32) -> Option<T>
128where
129 T: DeserializeOwned,
130{
131 let doc = IoDocument::new(id);
132 let doc = BufReader::with_capacity(doc.len(), doc);
133 match serde_json::from_reader::<BufReader<IoDocument>, T>(doc) {
134 Ok(response) => Some(response),
135 Err(why) => {
136 console_log(format!("[ERROR] ioid={} {}", id, why.to_string()));
137 None
138 }
139 }
140}
141
142pub static mut FUNCTION_INPUT_BUFFER: [u8; FUNCTION_INPUT_BUFFER_SIZE] =
145 [0; FUNCTION_INPUT_BUFFER_SIZE];
146
147#[no_mangle]
149pub fn __asml_guest_get_function_input_buffer_pointer() -> *const u8 {
150 unsafe { FUNCTION_INPUT_BUFFER.as_ptr() }
151}
152
153pub struct FunctionInputBuffer {
154 bytes_read: usize,
155 pages_read: usize,
156 length: usize,
157}
158
159impl FunctionInputBuffer {
160 pub fn new() -> Self {
161 unsafe { __asml_abi_input_start() };
162 Self {
163 bytes_read: 0usize,
164 pages_read: 0usize,
165 length: unsafe { __asml_abi_input_length_get() as usize },
166 }
167 }
168}
169
170impl std::io::Read for FunctionInputBuffer {
171 fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
172 let mut bytes_read = 0usize;
173 if self.bytes_read < self.length {
174 for idx in 0..std::cmp::min(self.length, buf.len()) {
175 buf[idx] = unsafe {
178 FUNCTION_INPUT_BUFFER[self.bytes_read % FUNCTION_INPUT_BUFFER_SIZE]
179 };
180 bytes_read += 1;
181 self.bytes_read += 1;
182 if self.bytes_read % FUNCTION_INPUT_BUFFER_SIZE == 0 {
183 unsafe { __asml_abi_input_next() };
184 self.pages_read += 1;
185 }
186 }
187 }
188 Ok(bytes_read)
189 }
190}