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