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