wars_rt/
lib.rs

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}
33// use as_ref::AsSlice;
34// use func::CtxSpec;
35pub 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}
199// pub unsafe fn host_memory() -> impl Memory {
200//     struct W {}
201//     impl Memory for W {
202//         fn read<'a>(&'a self, a: u64, s: u64) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>> {
203//             return Ok(Box::new(unsafe {
204//                 core::slice::from_raw_parts(a as usize as *const u8, s as usize)
205//             }));
206//         }
207
208//         fn write(&mut self, a: u64, x: &[u8]) -> anyhow::Result<()> {
209//             let n = unsafe { core::slice::from_raw_parts_mut(a as usize as *mut u8, x.len()) };
210//             n.copy_from_slice(x);
211//             return Ok(());
212//         }
213
214//         fn size(&self) -> Result<u64, anyhow::Error> {
215//             anyhow::bail!("host memory cannot use size")
216//         }
217
218//         fn grow(&mut self, x: u64) -> anyhow::Result<()> {
219//             anyhow::bail!("host memory cannot use grow")
220//         }
221//     }
222//     return W {};
223// }
224pub 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            //comparisons
279            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            //signed
329            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            //LOADS and STORES
370            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                // let mut r = &mut a[b.try_into().map_err(Into::into)?..][..std::mem::size_of::<$int>()];
376                // r.copy_from_slice(&c.to_ne_bytes());
377                a.write(b.try_into().map_err(Into::into)?,&c.to_ne_bytes())?;
378                Ok(())
379            }
380            //8 BIT
381            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                // let mut r = &mut a[b.try_into().map_err(Into::into)?..][..1];
391                // r[0] = (c & 0xff) as u8;
392                a.write(b.try_into().map_err(Into::into)?,&[(c & 0xff) as u8])?;
393                Ok(())
394            }
395            //16 BIT
396            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                // let mut r = &mut a[b.try_into().map_err(Into::into)?..][..2];
408                a.write(b.try_into().map_err(Into::into)?,&((c & 0xffff) as u16).to_ne_bytes())?;
409                Ok(())
410            }
411            //32 BIT
412            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                // let mut r = &mut a[b.try_into().map_err(Into::into)?..][..4];
424                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}