1#![no_std]
2extern crate alloc;
3pub use core::convert::Infallible;
4pub use either::Either;
5pub mod func;
6pub mod wasix;
7#[cfg(feature = "dumpster")]
8pub mod gc;
9use alloc::{boxed::Box, sync::Arc, vec::Vec};
10use core::iter::empty;
11#[cfg(feature = "std")]
12pub use std::sync::Mutex;
13#[cfg(not(feature = "std"))]
14pub use spin::Mutex;
15pub trait Err: Into<anyhow::Error> {}
16impl<T: Into<anyhow::Error>> Err for T {}
17#[cfg(feature = "std")]
18extern crate std;
19#[derive(Clone)]
20pub enum Pit<X, H> {
21 Guest { id: [u8; 32], x: X, s: [u8; 32] },
22 Host { host: H },
23}
24pub use func::Value;
27pub trait CtxSpec: Sized {
28 type ExternRef: Clone;
29}
30pub trait Traverse<C: CtxSpec> {
31 fn traverse<'a>(&'a self) -> Box<dyn Iterator<Item = &'a C::ExternRef> + 'a>;
32 fn traverse_mut<'a>(&'a mut self) -> Box<dyn Iterator<Item = &'a mut C::ExternRef> + 'a>;
33}
34impl<C: CtxSpec, V: Traverse<C>> Traverse<C> for Vec<V> {
35 fn traverse<'a>(&'a self) -> Box<dyn Iterator<Item = &'a <C as CtxSpec>::ExternRef> + 'a> {
36 Box::new(self.iter().flat_map(|a| a.traverse()))
37 }
38 fn traverse_mut<'a>(
39 &'a mut self,
40 ) -> Box<dyn Iterator<Item = &'a mut <C as CtxSpec>::ExternRef> + 'a> {
41 Box::new(self.iter_mut().flat_map(|x| x.traverse_mut()))
42 }
43}
44impl<C: CtxSpec> Traverse<C> for u32 {
45 fn traverse<'a>(&'a self) -> Box<dyn Iterator<Item = &'a <C as CtxSpec>::ExternRef> + 'a> {
46 Box::new(empty())
47 }
48 fn traverse_mut<'a>(
49 &'a mut self,
50 ) -> Box<dyn Iterator<Item = &'a mut <C as CtxSpec>::ExternRef> + 'a> {
51 Box::new(empty())
52 }
53}
54impl<C: CtxSpec> Traverse<C> for u64 {
55 fn traverse<'a>(&'a self) -> Box<dyn Iterator<Item = &'a <C as CtxSpec>::ExternRef> + 'a> {
56 Box::new(empty())
57 }
58 fn traverse_mut<'a>(
59 &'a mut self,
60 ) -> Box<dyn Iterator<Item = &'a mut <C as CtxSpec>::ExternRef> + 'a> {
61 Box::new(empty())
62 }
63}
64pub trait Memory {
65 fn read<'a>(&'a self, a: u64, s: u64) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>>;
66 fn write(&mut self, a: u64, x: &[u8]) -> anyhow::Result<()>;
67 fn size(&self) -> anyhow::Result<u64>;
68 fn grow(&mut self, x: u64) -> anyhow::Result<()>;
69}
70#[cfg(feature = "ic-stable-structures")]
71pub mod ic {
72 use alloc::{boxed::Box, vec};
73 #[repr(transparent)]
74 pub struct Stable<T>(pub T);
75 impl<T: ic_stable_structures::Memory> super::Memory for Stable<T> {
76 fn read<'a>(&'a self, a: u64, s: u64) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>> {
77 let mut v = vec![0u8; s as usize];
78 self.0.read(a, &mut v);
79 Ok(Box::new(v))
80 }
81 fn write(&mut self, a: u64, x: &[u8]) -> anyhow::Result<()> {
82 self.0.write(a, x);
83 Ok(())
84 }
85 fn size(&self) -> anyhow::Result<u64> {
86 let s = self.0.size();
87 Ok(s * 65536)
88 }
89 fn grow(&mut self, x: u64) -> anyhow::Result<()> {
90 if self.0.grow((x + 65535) / 65536) == -1 {
91 anyhow::bail!("stable growth failed")
92 }
93 Ok(())
94 }
95 }
96}
97impl Memory for Vec<u8> {
98 fn read<'a>(&'a self, a: u64, s: u64) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>> {
99 Ok(Box::new(&self[(a as usize)..][..(s as usize)]))
100 }
101 fn write(&mut self, a: u64, x: &[u8]) -> anyhow::Result<()> {
102 self[(a as usize)..][..x.len()].copy_from_slice(x);
103 Ok(())
104 }
105 fn size(&self) -> anyhow::Result<u64> {
106 Ok(self.len() as u64)
107 }
108 fn grow(&mut self, x: u64) -> anyhow::Result<()> {
109 self.extend((0..x).map(|a| 0u8));
110 Ok(())
111 }
112}
113impl<T: Memory + ?Sized> Memory for Box<T> {
114 fn read<'a>(&'a self, a: u64, s: u64) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>> {
115 self.as_ref().read(a, s)
116 }
117 fn write(&mut self, a: u64, x: &[u8]) -> anyhow::Result<()> {
118 self.as_mut().write(a, x)
119 }
120 fn size(&self) -> Result<u64, anyhow::Error> {
121 self.as_ref().size()
122 }
123 fn grow(&mut self, x: u64) -> anyhow::Result<()> {
124 self.as_mut().grow(x)
125 }
126}
127#[cfg(feature = "std")]
128impl<T: Memory> Memory for Arc<std::sync::Mutex<T>> {
129 fn read<'a>(&'a self, a: u64, s: u64) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>> {
130 let l = self.lock().unwrap();
131 let r = l.read(a, s)?;
132 return Ok(Box::new(r.as_ref().as_ref().to_vec()));
133 }
134 fn write(&mut self, a: u64, x: &[u8]) -> anyhow::Result<()> {
135 let mut l = self.lock().unwrap();
136 return l.write(a, x);
137 }
138 fn size(&self) -> Result<u64, anyhow::Error> {
139 let l = self.lock().unwrap();
140 return l.size();
141 }
142 fn grow(&mut self, x: u64) -> anyhow::Result<()> {
143 let mut l = self.lock().unwrap();
144 return l.grow(x);
145 }
146}
147#[cfg(not(feature = "std"))]
148impl<T: Memory> Memory for Arc<spin::Mutex<T>> {
149 fn read<'a>(&'a self, a: u64, s: u64) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>> {
150 let l = self.lock();
151 let r = l.read(a, s)?;
152 return Ok(Box::new(r.as_ref().as_ref().to_vec()));
153 }
154 fn write(&mut self, a: u64, x: &[u8]) -> anyhow::Result<()> {
155 let mut l = self.lock();
156 return l.write(a, x);
157 }
158 fn size(&self) -> Result<u64, anyhow::Error> {
159 let l = self.lock();
160 return l.size();
161 }
162 fn grow(&mut self, x: u64) -> anyhow::Result<()> {
163 let mut l = self.lock();
164 return l.grow(x);
165 }
166}
167pub mod _rexport {
190 pub use anyhow;
191 pub use tramp;
192 pub use tuple_list;
193 pub extern crate alloc;
194}
195macro_rules! int_ty{
196 ($int:ty => $p:ident) => {
197 paste::paste!{
198 pub fn [<$p add>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
199 Ok(tuple_list::tuple_list!(a.wrapping_add(b)))
200 }
201 pub fn [<$p mul>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
202 Ok(tuple_list::tuple_list!(a.wrapping_mul(b)))
203 }
204 pub fn [<$p and>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
205 Ok(tuple_list::tuple_list!(a & b))
206 }
207 pub fn [<$p or>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
208 Ok(tuple_list::tuple_list!(a | b))
209 }
210 pub fn [<$p xor>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
211 Ok(tuple_list::tuple_list!(a ^ b))
212 }
213 pub fn [<$p shl>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
214 Ok(tuple_list::tuple_list!(a << b))
215 }
216 pub fn [<$p shru>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
217 Ok(tuple_list::tuple_list!(a >> b))
218 }
219 pub fn [<$p shrs>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
220 Ok(tuple_list::tuple_list!(((a as $p) >> b) as $int))
221 }
222 pub fn [<$p divu>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
223 Ok(tuple_list::tuple_list!(a / b))
224 }
225 pub fn [<$p divs>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
226 Ok(tuple_list::tuple_list!(((a as $p) / (b as $p)) as $int))
227 }
228 pub fn [<$p remu>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
229 Ok(tuple_list::tuple_list!(a % b))
230 }
231 pub fn [<$p rems>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
232 Ok(tuple_list::tuple_list!(((a as $p) % (b as $p)) as $int))
233 }
234 pub fn [<$p rotl>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
235 Ok(tuple_list::tuple_list!(a.rotate_left((b & 0xffffffff) as u32)))
236 }
237 pub fn [<$p clz>](a: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
238 Ok(tuple_list::tuple_list!(a.leading_zeros() as $int))
239 }
240 pub fn [<$p ctz>](a: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
241 Ok(tuple_list::tuple_list!(a.trailing_zeros() as $int))
242 }
243 pub fn [<$p eqz>](a: $int) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
245 Ok(tuple_list::tuple_list!(if a == 0{
246 1
247 }else{
248 0
249 }))
250 }
251 pub fn [<$p eq>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
252 Ok(tuple_list::tuple_list!(if a == b{
253 1
254 }else{
255 0
256 }))
257 }
258 pub fn [<$p ne>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
259 Ok(tuple_list::tuple_list!(if a != b{
260 1
261 }else{
262 0
263 }))
264 }
265 pub fn [<$p ltu>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
266 Ok(tuple_list::tuple_list!(if a < b{
267 1
268 }else{
269 0
270 }))
271 }
272 pub fn [<$p gtu>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
273 Ok(tuple_list::tuple_list!(if a > b{
274 1
275 }else{
276 0
277 }))
278 }
279 pub fn [<$p leu>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
280 Ok(tuple_list::tuple_list!(if a <= b{
281 1
282 }else{
283 0
284 }))
285 }
286 pub fn [<$p geu>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
287 Ok(tuple_list::tuple_list!(if a >= b{
288 1
289 }else{
290 0
291 }))
292 }
293 pub fn [<$p lts>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
295 let a = a as $p;
296 let b = b as $p;
297 Ok(tuple_list::tuple_list!(if a < b{
298 1
299 }else{
300 0
301 }))
302 }
303 pub fn [<$p gts>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
304 let a = a as $p;
305 let b = b as $p;
306 Ok(tuple_list::tuple_list!(if a > b{
307 1
308 }else{
309 0
310 }))
311 }
312 pub fn [<$p les>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
313 let a = a as $p;
314 let b = b as $p;
315 Ok(tuple_list::tuple_list!(if a <= b{
316 1
317 }else{
318 0
319 }))
320 }
321 pub fn [<$p ges>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
322 let a = a as $p;
323 let b = b as $p;
324 Ok(tuple_list::tuple_list!(if a >= b{
325 1
326 }else{
327 0
328 }))
329 }
330 pub fn [<$p sub>](a: $int, b: $int) -> anyhow::Result<tuple_list::tuple_list_type!($int)> {
331 Ok(tuple_list::tuple_list!(a.wrapping_sub(b)))
332 }
333 pub fn [<$p load>]<T: TryInto<u64>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: Err + Send + Sync + 'static{
335 let r = a.read(b.try_into().map_err(Into::into)?,core::mem::size_of::<$int>().try_into().unwrap())?;
336 Ok(tuple_list::tuple_list!($int::from_ne_bytes(r.as_ref().as_ref().try_into().unwrap())))
337 }
338 pub fn [<$p store>]<T: TryInto<u64>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: Err + Send + Sync + 'static{
339 a.write(b.try_into().map_err(Into::into)?,&c.to_ne_bytes())?;
342 Ok(())
343 }
344 pub fn [<$p load8u>]<T: TryInto<u64>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: Err + Send + Sync + 'static{
346 let r = a.read(b.try_into().map_err(Into::into)?,1)?.as_ref().as_ref()[0];
347 Ok(tuple_list::tuple_list!(r as $int))
348 }
349 pub fn [<$p load8s>]<T: TryInto<u64>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: Err + Send + Sync + 'static{
350 let r = a.read(b.try_into().map_err(Into::into)?,1)?.as_ref().as_ref()[0];
351 Ok(tuple_list::tuple_list!(r as i8 as $p as $int))
352 }
353 pub fn [<$p store8>]<T: TryInto<u64>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: Err + Send + Sync + 'static{
354 a.write(b.try_into().map_err(Into::into)?,&[(c & 0xff) as u8])?;
357 Ok(())
358 }
359 pub fn [<$p load16u>]<T: TryInto<u64>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: Err + Send + Sync + 'static{
361 let r = a.read(b.try_into().map_err(Into::into)?,2)?;
362 let r = u16::from_ne_bytes(r.as_ref().as_ref().try_into().unwrap());
363 Ok(tuple_list::tuple_list!(r as $int))
364 }
365 pub fn [<$p load16s>]<T: TryInto<u64>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: Err + Send + Sync + 'static{
366 let r = a.read(b.try_into().map_err(Into::into)?,2)?;
367 let r = u16::from_ne_bytes(r.as_ref().as_ref().try_into().unwrap());
368 Ok(tuple_list::tuple_list!(r as i16 as $p as $int))
369 }
370 pub fn [<$p store16>]<T: TryInto<u64>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: Err + Send + Sync + 'static{
371 a.write(b.try_into().map_err(Into::into)?,&((c & 0xffff) as u16).to_ne_bytes())?;
373 Ok(())
374 }
375 pub fn [<$p load32u>]<T: TryInto<u64>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: Err + Send + Sync + 'static{
377 let r = a.read(b.try_into().map_err(Into::into)?,4)?;
378 let r = u32::from_ne_bytes(r.as_ref().as_ref().try_into().unwrap());
379 Ok(tuple_list::tuple_list!(r as $int))
380 }
381 pub fn [<$p load32s>]<T: TryInto<u64>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: Err + Send + Sync + 'static{
382 let r = a.read(b.try_into().map_err(Into::into)?,4)?;
383 let r = u32::from_ne_bytes(r.as_ref().as_ref().try_into().unwrap());
384 Ok(tuple_list::tuple_list!(r as i32 as $p as $int))
385 }
386 pub fn [<$p store32>]<T: TryInto<u64>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: Err + Send + Sync + 'static{
387 a.write(b.try_into().map_err(Into::into)?,&((c & 0xffffffff) as u32).to_ne_bytes())?;
389 Ok(())
390 }
391 }
392 }
393}
394int_ty!(u32 => i32);
395int_ty!(u64 => i64);
396pub fn select<T>(u: u32, t: T, t2: T) -> anyhow::Result<tuple_list::tuple_list_type!(T)> {
397 Ok(tuple_list::tuple_list!(if u != 0 { t } else { t2 }))
398}
399pub fn i32wrapi64(a: u64) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
400 return Ok(tuple_list::tuple_list!((a & 0xffffffff) as u32));
401}
402pub fn i64extendi32u(a: u32) -> anyhow::Result<tuple_list::tuple_list_type!(u64)> {
403 Ok(tuple_list::tuple_list!(a as u64))
404}
405pub fn i64extendi32s(a: u32) -> anyhow::Result<tuple_list::tuple_list_type!(u64)> {
406 Ok(tuple_list::tuple_list!(a as i32 as i64 as u64))
407}
408pub fn i64truncf64s(a: f64) -> anyhow::Result<tuple_list::tuple_list_type!(u64)> {
409 Ok(tuple_list::tuple_list!(
410 unsafe { a.trunc().to_int_unchecked::<i64>() } as u64
411 ))
412}