wars_rt/
lib.rs

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}
24// use as_ref::AsSlice;
25// use func::CtxSpec;
26pub 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}
167// pub unsafe fn host_memory() -> impl Memory {
168//     struct W {}
169//     impl Memory for W {
170//         fn read<'a>(&'a self, a: u64, s: u64) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>> {
171//             return Ok(Box::new(unsafe {
172//                 core::slice::from_raw_parts(a as usize as *const u8, s as usize)
173//             }));
174//         }
175//         fn write(&mut self, a: u64, x: &[u8]) -> anyhow::Result<()> {
176//             let n = unsafe { core::slice::from_raw_parts_mut(a as usize as *mut u8, x.len()) };
177//             n.copy_from_slice(x);
178//             return Ok(());
179//         }
180//         fn size(&self) -> Result<u64, anyhow::Error> {
181//             anyhow::bail!("host memory cannot use size")
182//         }
183//         fn grow(&mut self, x: u64) -> anyhow::Result<()> {
184//             anyhow::bail!("host memory cannot use grow")
185//         }
186//     }
187//     return W {};
188// }
189pub 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            //comparisons
244            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            //signed
294            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            //LOADS and STORES
334            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                // let mut r = &mut a[b.try_into().map_err(Into::into)?..][..std::mem::size_of::<$int>()];
340                // r.copy_from_slice(&c.to_ne_bytes());
341                a.write(b.try_into().map_err(Into::into)?,&c.to_ne_bytes())?;
342                Ok(())
343            }
344            //8 BIT
345            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                // let mut r = &mut a[b.try_into().map_err(Into::into)?..][..1];
355                // r[0] = (c & 0xff) as u8;
356                a.write(b.try_into().map_err(Into::into)?,&[(c & 0xff) as u8])?;
357                Ok(())
358            }
359            //16 BIT
360            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                // let mut r = &mut a[b.try_into().map_err(Into::into)?..][..2];
372                a.write(b.try_into().map_err(Into::into)?,&((c & 0xffff) as u16).to_ne_bytes())?;
373                Ok(())
374            }
375            //32 BIT
376            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                // let mut r = &mut a[b.try_into().map_err(Into::into)?..][..4];
388                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}