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