1#![forbid(unsafe_code)]
2#![warn(missing_docs)]
3#![warn(clippy::missing_docs_in_private_items)]
4#![cfg_attr(not(feature = "std"), no_std)]
5
6extern crate alloc;
78
79use alloc::{
80 boxed::Box,
81 string::{String, ToString},
82 sync::Arc,
83 vec::Vec,
84};
85use core::{any::Any, fmt};
86
87use anyhow::Result;
88use fxhash::FxBuildHasher;
89use hashbrown::HashMap;
90use ref_cast::RefCast;
91use smallvec::SmallVec;
92
93use crate::backend::*;
94
95pub mod backend;
97
98const DEFAULT_ARGUMENT_SIZE: usize = 4;
101
102type ArgumentVec<T> = SmallVec<[T; DEFAULT_ARGUMENT_SIZE]>;
104
105#[derive(Copy, Clone, Debug, PartialEq, Eq)]
107pub enum ValueType {
108 I32,
110 I64,
112 F32,
114 F64,
116 FuncRef,
118 ExternRef,
120}
121
122impl fmt::Display for ValueType {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 match self {
125 ValueType::I32 => write!(f, "i32"),
126 ValueType::I64 => write!(f, "i64"),
127 ValueType::F32 => write!(f, "f32"),
128 ValueType::F64 => write!(f, "f64"),
129 ValueType::FuncRef => write!(f, "funcref"),
130 ValueType::ExternRef => write!(f, "externref"),
131 }
132 }
133}
134
135#[derive(Copy, Clone, Debug, PartialEq, Eq)]
137pub struct GlobalType {
138 content: ValueType,
140 mutable: bool,
142}
143
144impl GlobalType {
145 pub fn new(content: ValueType, mutable: bool) -> Self {
147 Self { content, mutable }
148 }
149
150 pub fn content(&self) -> ValueType {
152 self.content
153 }
154
155 pub fn mutable(&self) -> bool {
157 self.mutable
158 }
159}
160
161#[derive(Copy, Clone, Debug, PartialEq, Eq)]
163pub struct TableType {
164 element: ValueType,
166 min: u32,
168 max: Option<u32>,
172}
173
174impl TableType {
175 pub fn new(element: ValueType, min: u32, max: Option<u32>) -> Self {
181 if let Some(max) = max {
182 assert!(min <= max);
183 }
184 Self { element, min, max }
185 }
186
187 pub fn element(&self) -> ValueType {
189 self.element
190 }
191
192 pub fn minimum(&self) -> u32 {
194 self.min
195 }
196
197 pub fn maximum(&self) -> Option<u32> {
201 self.max
202 }
203}
204
205#[derive(Copy, Clone, Debug, PartialEq, Eq)]
207pub struct MemoryType {
208 initial: u32,
210 maximum: Option<u32>,
212}
213
214impl MemoryType {
215 pub fn new(initial: u32, maximum: Option<u32>) -> Self {
217 Self { initial, maximum }
218 }
219
220 pub fn initial_pages(self) -> u32 {
222 self.initial
223 }
224
225 pub fn maximum_pages(self) -> Option<u32> {
232 self.maximum
233 }
234}
235
236#[derive(Clone)]
242pub struct FuncType {
243 len_params: usize,
245 params_results: Arc<[ValueType]>,
255 name: Option<Arc<str>>,
257}
258
259impl fmt::Debug for FuncType {
260 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
261 f.debug_struct("FuncType")
262 .field("params", &self.params())
263 .field("results", &self.results())
264 .field("name", &self.name)
265 .finish()
266 }
267}
268
269impl PartialEq for FuncType {
270 fn eq(&self, other: &Self) -> bool {
271 self.len_params == other.len_params && self.params_results == other.params_results
272 }
273}
274
275impl Eq for FuncType {}
276
277impl fmt::Display for FuncType {
278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279 let params = self.params();
280 let results = self.results();
281
282 let mut first = true;
283
284 write!(f, "func(")?;
285 for param in params {
286 if !first {
287 write!(f, ", ")?;
288 } else {
289 first = false;
290 }
291 write!(f, "{param}")?;
292 }
293
294 let mut first = true;
295
296 write!(f, ")")?;
297 for result in results {
298 if !first {
299 first = false;
300 write!(f, ", ")?;
301 } else {
302 write!(f, " -> ")?;
303 }
304 write!(f, "{result}")?;
305 }
306 Ok(())
307 }
308}
309
310impl FuncType {
311 pub fn new<P, R>(params: P, results: R) -> Self
313 where
314 P: IntoIterator<Item = ValueType>,
315 R: IntoIterator<Item = ValueType>,
316 {
317 let mut params_results = params.into_iter().collect::<Vec<_>>();
318 let len_params = params_results.len();
319 params_results.extend(results);
320 Self {
321 params_results: params_results.into(),
322 len_params,
323 name: None,
324 }
325 }
326
327 pub fn params(&self) -> &[ValueType] {
329 &self.params_results[..self.len_params]
330 }
331
332 pub fn results(&self) -> &[ValueType] {
334 &self.params_results[self.len_params..]
335 }
336
337 pub fn with_name(mut self, name: impl Into<Arc<str>>) -> Self {
339 self.name = Some(name.into());
340 self
341 }
342}
343
344#[derive(Clone, Debug)]
348pub enum ExternType {
349 Global(GlobalType),
351 Table(TableType),
353 Memory(MemoryType),
355 Func(FuncType),
357}
358
359impl From<GlobalType> for ExternType {
360 fn from(global: GlobalType) -> Self {
361 Self::Global(global)
362 }
363}
364
365impl From<TableType> for ExternType {
366 fn from(table: TableType) -> Self {
367 Self::Table(table)
368 }
369}
370
371impl From<MemoryType> for ExternType {
372 fn from(memory: MemoryType) -> Self {
373 Self::Memory(memory)
374 }
375}
376
377impl From<FuncType> for ExternType {
378 fn from(func: FuncType) -> Self {
379 Self::Func(func)
380 }
381}
382
383impl ExternType {
384 pub fn global(&self) -> Option<&GlobalType> {
386 match self {
387 Self::Global(ty) => Some(ty),
388 _ => None,
389 }
390 }
391
392 pub fn table(&self) -> Option<&TableType> {
394 match self {
395 Self::Table(ty) => Some(ty),
396 _ => None,
397 }
398 }
399
400 pub fn memory(&self) -> Option<&MemoryType> {
402 match self {
403 Self::Memory(ty) => Some(ty),
404 _ => None,
405 }
406 }
407
408 pub fn func(&self) -> Option<&FuncType> {
410 match self {
411 Self::Func(ty) => Some(ty),
412 _ => None,
413 }
414 }
415
416 pub fn try_into_func(self) -> core::result::Result<FuncType, Self> {
418 if let Self::Func(v) = self {
419 Ok(v)
420 } else {
421 Err(self)
422 }
423 }
424
425 pub fn try_into_table(self) -> Result<TableType, Self> {
427 if let Self::Table(v) = self {
428 Ok(v)
429 } else {
430 Err(self)
431 }
432 }
433
434 pub fn try_into_global(self) -> Result<GlobalType, Self> {
436 if let Self::Global(v) = self {
437 Ok(v)
438 } else {
439 Err(self)
440 }
441 }
442
443 pub fn try_into_memory(self) -> Result<MemoryType, Self> {
445 if let Self::Memory(v) = self {
446 Ok(v)
447 } else {
448 Err(self)
449 }
450 }
451}
452
453#[derive(Clone, Debug)]
458pub struct ExportType<'module> {
459 pub name: &'module str,
461 pub ty: ExternType,
463}
464
465#[derive(Clone, Debug)]
471pub struct ImportType<'module> {
472 pub module: &'module str,
474 pub name: &'module str,
476 pub ty: ExternType,
478}
479
480#[derive(Clone, Debug)]
485pub enum Extern {
486 Global(Global),
490 Table(Table),
492 Memory(Memory),
494 Func(Func),
496}
497
498impl Extern {
499 pub fn into_global(self) -> Option<Global> {
503 if let Self::Global(global) = self {
504 return Some(global);
505 }
506 None
507 }
508
509 pub fn into_table(self) -> Option<Table> {
513 if let Self::Table(table) = self {
514 return Some(table);
515 }
516 None
517 }
518
519 pub fn into_memory(self) -> Option<Memory> {
523 if let Self::Memory(memory) = self {
524 return Some(memory);
525 }
526 None
527 }
528
529 pub fn into_func(self) -> Option<Func> {
533 if let Self::Func(func) = self {
534 return Some(func);
535 }
536 None
537 }
538
539 pub fn ty(&self, ctx: impl AsContext) -> ExternType {
541 match self {
542 Extern::Global(global) => global.ty(ctx).into(),
543 Extern::Table(table) => table.ty(ctx).into(),
544 Extern::Memory(memory) => memory.ty(ctx).into(),
545 Extern::Func(func) => func.ty(ctx).into(),
546 }
547 }
548}
549
550impl<E: WasmEngine> From<&crate::backend::Extern<E>> for Extern {
551 fn from(value: &crate::backend::Extern<E>) -> Self {
552 match value {
553 crate::backend::Extern::Global(x) => Self::Global(Global {
554 global: BackendObject::new(x.clone()),
555 }),
556 crate::backend::Extern::Table(x) => Self::Table(Table {
557 table: BackendObject::new(x.clone()),
558 }),
559 crate::backend::Extern::Memory(x) => Self::Memory(Memory {
560 memory: BackendObject::new(x.clone()),
561 }),
562 crate::backend::Extern::Func(x) => Self::Func(Func {
563 func: BackendObject::new(x.clone()),
564 }),
565 }
566 }
567}
568
569impl<E: WasmEngine> From<&Extern> for crate::backend::Extern<E> {
570 fn from(value: &Extern) -> Self {
571 match value {
572 Extern::Global(x) => Self::Global(x.global.cast::<E::Global>().clone()),
573 Extern::Table(x) => Self::Table(x.table.cast::<E::Table>().clone()),
574 Extern::Memory(x) => Self::Memory(x.memory.cast::<E::Memory>().clone()),
575 Extern::Func(x) => Self::Func(x.func.cast::<E::Func>().clone()),
576 }
577 }
578}
579
580pub struct Export {
585 pub name: String,
587 pub value: Extern,
589}
590
591impl<E: WasmEngine> From<crate::backend::Export<E>> for Export {
592 fn from(value: crate::backend::Export<E>) -> Self {
593 Self {
594 name: value.name,
595 value: (&value.value).into(),
596 }
597 }
598}
599
600#[derive(Clone, Debug)]
602pub struct Imports {
603 pub(crate) map: HashMap<(String, String), Extern, FxBuildHasher>,
605}
606
607impl Imports {
608 pub fn new() -> Self {
610 Self {
611 map: HashMap::default(),
612 }
613 }
614
615 pub fn get_export(&self, module: &str, name: &str) -> Option<Extern> {
617 if self.exists(module, name) {
618 let ext = &self.map[&(module.to_string(), name.to_string())];
619 return Some(ext.clone());
620 }
621 None
622 }
623
624 pub fn exists(&self, module: &str, name: &str) -> bool {
626 self.map
627 .contains_key(&(module.to_string(), name.to_string()))
628 }
629
630 pub fn contains_namespace(&self, name: &str) -> bool {
632 self.map.keys().any(|(k, _)| (k == name))
633 }
634
635 pub fn register_namespace(
637 &mut self,
638 ns: &str,
639 contents: impl IntoIterator<Item = (String, Extern)>,
640 ) {
641 for (name, extern_) in contents.into_iter() {
642 self.map.insert((ns.to_string(), name.clone()), extern_);
643 }
644 }
645
646 pub fn define(&mut self, ns: &str, name: &str, val: impl Into<Extern>) {
648 self.map
649 .insert((ns.to_string(), name.to_string()), val.into());
650 }
651
652 pub fn iter(&self) -> ImportsIterator {
654 ImportsIterator::new(self)
655 }
656}
657
658pub struct ImportsIterator<'a> {
660 iter: hashbrown::hash_map::Iter<'a, (String, String), Extern>,
662}
663
664impl<'a> ImportsIterator<'a> {
665 fn new(imports: &'a Imports) -> Self {
667 let iter = imports.map.iter();
668 Self { iter }
669 }
670}
671
672impl<'a> Iterator for ImportsIterator<'a> {
673 type Item = (&'a str, &'a str, &'a Extern);
674
675 fn next(&mut self) -> Option<Self::Item> {
676 self.iter
677 .next()
678 .map(|(k, v)| (k.0.as_str(), k.1.as_str(), v))
679 }
680}
681
682impl IntoIterator for &Imports {
683 type IntoIter = hashbrown::hash_map::IntoIter<(String, String), Extern>;
684 type Item = ((String, String), Extern);
685
686 fn into_iter(self) -> Self::IntoIter {
687 self.map.clone().into_iter()
688 }
689}
690
691impl Default for Imports {
692 fn default() -> Self {
693 Self::new()
694 }
695}
696
697impl Extend<((String, String), Extern)> for Imports {
698 fn extend<T: IntoIterator<Item = ((String, String), Extern)>>(&mut self, iter: T) {
699 for ((ns, name), ext) in iter.into_iter() {
700 self.define(&ns, &name, ext);
701 }
702 }
703}
704
705#[derive(RefCast, Clone)]
707#[repr(transparent)]
708pub struct Engine<E: WasmEngine> {
709 backend: E,
711}
712
713impl<E: WasmEngine> Engine<E> {
714 pub fn new(backend: E) -> Self {
716 Self { backend }
717 }
718
719 pub fn into_backend(self) -> E {
721 self.backend
722 }
723}
724
725pub struct Store<T: 'static, E: WasmEngine> {
735 inner: E::Store<T>,
737}
738
739impl<T: 'static, E: WasmEngine> Store<T, E> {
740 pub fn new(engine: &Engine<E>, data: T) -> Self {
742 Self {
743 inner: <E::Store<T> as WasmStore<T, E>>::new(&engine.backend, data),
744 }
745 }
746
747 pub fn engine(&self) -> &Engine<E> {
749 Engine::<E>::ref_cast(self.inner.engine())
750 }
751
752 pub fn data(&self) -> &T {
754 self.inner.data()
755 }
756
757 pub fn data_mut(&mut self) -> &mut T {
759 self.inner.data_mut()
760 }
761
762 pub fn into_data(self) -> T {
764 self.inner.into_data()
765 }
766}
767
768pub struct StoreContext<'a, T: 'static, E: WasmEngine> {
773 inner: E::StoreContext<'a, T>,
775}
776
777impl<'a, T: 'static, E: WasmEngine> StoreContext<'a, T, E> {
778 pub fn engine(&self) -> &Engine<E> {
780 Engine::<E>::ref_cast(self.inner.engine())
781 }
782
783 pub fn data(&self) -> &T {
787 self.inner.data()
788 }
789}
790
791pub struct StoreContextMut<'a, T: 'static, E: WasmEngine> {
796 pub inner: E::StoreContextMut<'a, T>,
798}
799
800impl<'a, T: 'static, E: WasmEngine> StoreContextMut<'a, T, E> {
801 pub fn engine(&self) -> &Engine<E> {
803 Engine::<E>::ref_cast(self.inner.engine())
804 }
805
806 pub fn data(&self) -> &T {
810 self.inner.data()
811 }
812
813 pub fn data_mut(&mut self) -> &mut T {
817 self.inner.data_mut()
818 }
819}
820
821#[derive(Clone, Debug)]
829pub enum Value {
830 I32(i32),
832 I64(i64),
834 F32(f32),
836 F64(f64),
838 FuncRef(Option<Func>),
840 ExternRef(Option<ExternRef>),
842}
843
844impl Value {
845 #[must_use]
847 pub const fn ty(&self) -> ValueType {
848 match self {
849 Value::I32(_) => ValueType::I32,
850 Value::I64(_) => ValueType::I64,
851 Value::F32(_) => ValueType::F32,
852 Value::F64(_) => ValueType::F64,
853 Value::FuncRef(_) => ValueType::FuncRef,
854 Value::ExternRef(_) => ValueType::ExternRef,
855 }
856 }
857}
858
859impl PartialEq for Value {
860 fn eq(&self, o: &Self) -> bool {
861 match (self, o) {
862 (Self::I32(a), Self::I32(b)) => a == b,
863 (Self::I64(a), Self::I64(b)) => a == b,
864 (Self::F32(a), Self::F32(b)) => a == b,
865 (Self::F64(a), Self::F64(b)) => a == b,
866 _ => false,
867 }
868 }
869}
870
871impl<E: WasmEngine> From<&Value> for crate::backend::Value<E> {
872 fn from(value: &Value) -> Self {
873 match value {
874 Value::I32(i32) => Self::I32(*i32),
875 Value::I64(i64) => Self::I64(*i64),
876 Value::F32(f32) => Self::F32(*f32),
877 Value::F64(f64) => Self::F64(*f64),
878 Value::FuncRef(None) => Self::FuncRef(None),
879 Value::FuncRef(Some(func)) => Self::FuncRef(Some(func.func.cast::<E::Func>().clone())),
880 Value::ExternRef(None) => Self::ExternRef(None),
881 Value::ExternRef(Some(extern_ref)) => {
882 Self::ExternRef(Some(extern_ref.extern_ref.cast::<E::ExternRef>().clone()))
883 }
884 }
885 }
886}
887
888impl<E: WasmEngine> From<&backend::Value<E>> for Value {
889 fn from(value: &crate::backend::Value<E>) -> Self {
890 match value {
891 crate::backend::Value::I32(i32) => Self::I32(*i32),
892 crate::backend::Value::I64(i64) => Self::I64(*i64),
893 crate::backend::Value::F32(f32) => Self::F32(*f32),
894 crate::backend::Value::F64(f64) => Self::F64(*f64),
895 crate::backend::Value::FuncRef(None) => Self::FuncRef(None),
896 crate::backend::Value::FuncRef(Some(func)) => Self::FuncRef(Some(Func {
897 func: BackendObject::new(func.clone()),
898 })),
899 crate::backend::Value::ExternRef(None) => Self::ExternRef(None),
900 crate::backend::Value::ExternRef(Some(extern_ref)) => {
901 Self::ExternRef(Some(ExternRef {
902 extern_ref: BackendObject::new(extern_ref.clone()),
903 }))
904 }
905 }
906 }
907}
908
909#[derive(Clone, Debug)]
911pub struct ExternRef {
912 extern_ref: BackendObject,
914}
915
916impl ExternRef {
917 pub fn new<T: 'static + Send + Sync, C: AsContextMut>(mut ctx: C, object: T) -> Self {
919 Self {
920 extern_ref: BackendObject::new(
921 <<C::Engine as WasmEngine>::ExternRef as WasmExternRef<C::Engine>>::new(
922 ctx.as_context_mut().inner,
923 object,
924 ),
925 ),
926 }
927 }
928
929 pub fn downcast<'a, 's: 'a, T: 'static, S: 'static, E: WasmEngine>(
931 &'a self,
932 ctx: StoreContext<'s, S, E>,
933 ) -> Result<&'a T> {
934 self.extern_ref.cast::<E::ExternRef>().downcast(ctx.inner)
935 }
936}
937
938#[derive(Clone, Debug)]
940pub struct Func {
941 func: BackendObject,
943}
944
945impl Func {
946 pub fn new<C: AsContextMut>(
948 mut ctx: C,
949 ty: FuncType,
950 func: impl 'static
951 + Send
952 + Sync
953 + Fn(StoreContextMut<'_, C::UserState, C::Engine>, &[Value], &mut [Value]) -> Result<()>,
954 ) -> Self {
955 let raw_func = <<C::Engine as WasmEngine>::Func as WasmFunc<C::Engine>>::new(
956 ctx.as_context_mut().inner,
957 ty,
958 move |ctx, args, results| {
959 let mut input = ArgumentVec::with_capacity(args.len());
960 input.extend(args.iter().map(Into::into));
961
962 let mut output = ArgumentVec::with_capacity(results.len());
963 output.extend(results.iter().map(Into::into));
964
965 func(StoreContextMut { inner: ctx }, &input, &mut output)?;
966
967 for (i, result) in output.iter().enumerate() {
968 results[i] = result.into();
969 }
970
971 Ok(())
972 },
973 );
974
975 Self {
976 func: BackendObject::new(raw_func),
977 }
978 }
979
980 pub fn ty<C: AsContext>(&self, ctx: C) -> FuncType {
982 self.func
983 .cast::<<C::Engine as WasmEngine>::Func>()
984 .ty(ctx.as_context().inner)
985 }
986
987 pub fn call<C: AsContextMut>(
991 &self,
992 mut ctx: C,
993 args: &[Value],
994 results: &mut [Value],
995 ) -> Result<()> {
996 let raw_func = self.func.cast::<<C::Engine as WasmEngine>::Func>();
997
998 let mut input = ArgumentVec::with_capacity(args.len());
999 input.extend(args.iter().map(Into::into));
1000
1001 let mut output = ArgumentVec::with_capacity(results.len());
1002 output.extend(results.iter().map(Into::into));
1003
1004 raw_func.call::<C::UserState>(ctx.as_context_mut().inner, &input, &mut output)?;
1005
1006 for (i, result) in output.iter().enumerate() {
1007 results[i] = result.into();
1008 }
1009
1010 Ok(())
1011 }
1012}
1013
1014#[derive(Clone, Debug)]
1016pub struct Global {
1017 global: BackendObject,
1019}
1020
1021impl Global {
1022 pub fn new<C: AsContextMut>(mut ctx: C, initial_value: Value, mutable: bool) -> Self {
1024 Self {
1025 global: BackendObject::new(<<C::Engine as WasmEngine>::Global as WasmGlobal<
1026 C::Engine,
1027 >>::new(
1028 ctx.as_context_mut().inner,
1029 (&initial_value).into(),
1030 mutable,
1031 )),
1032 }
1033 }
1034
1035 pub fn ty<C: AsContext>(&self, ctx: C) -> GlobalType {
1037 self.global
1038 .cast::<<C::Engine as WasmEngine>::Global>()
1039 .ty(ctx.as_context().inner)
1040 }
1041
1042 pub fn get<C: AsContextMut>(&self, mut ctx: C) -> Value {
1044 (&self
1045 .global
1046 .cast::<<C::Engine as WasmEngine>::Global>()
1047 .get(ctx.as_context_mut().inner))
1048 .into()
1049 }
1050
1051 pub fn set<C: AsContextMut>(&self, mut ctx: C, new_value: Value) -> Result<()> {
1053 self.global
1054 .cast::<<C::Engine as WasmEngine>::Global>()
1055 .set(ctx.as_context_mut().inner, (&new_value).into())
1056 }
1057}
1058
1059#[derive(Clone, Debug)]
1061pub struct Module {
1062 module: BackendObject,
1064}
1065
1066impl Module {
1067 pub fn new<E: WasmEngine>(engine: &Engine<E>, bytes: &[u8]) -> Result<Self> {
1069 Ok(Self {
1070 module: BackendObject::new(<E::Module as WasmModule<E>>::new(&engine.backend, bytes)?),
1071 })
1072 }
1073
1074 pub fn exports<E: WasmEngine>(
1076 &self,
1077 #[allow(unused_variables)] engine: &Engine<E>,
1078 ) -> impl '_ + Iterator<Item = ExportType<'_>> {
1079 self.module.cast::<E::Module>().exports()
1080 }
1081
1082 pub fn get_export<E: WasmEngine>(
1086 &self,
1087 #[allow(unused_variables)] engine: &Engine<E>,
1088 name: &str,
1089 ) -> Option<ExternType> {
1090 self.module.cast::<E::Module>().get_export(name)
1091 }
1092
1093 pub fn imports<E: WasmEngine>(
1095 &self,
1096 #[allow(unused_variables)] engine: &Engine<E>,
1097 ) -> impl '_ + Iterator<Item = ImportType<'_>> {
1098 self.module.cast::<E::Module>().imports()
1099 }
1100}
1101
1102#[derive(Clone, Debug)]
1111pub struct Instance {
1112 instance: BackendObject,
1114}
1115
1116impl Instance {
1117 pub fn new<C: AsContextMut>(mut ctx: C, module: &Module, imports: &Imports) -> Result<Self> {
1119 let mut backend_imports = crate::backend::Imports::default();
1120 backend_imports.extend(
1121 imports
1122 .into_iter()
1123 .map(|((host, name), val)| ((host, name), (&val).into())),
1124 );
1125
1126 Ok(Self {
1127 instance: BackendObject::new(<<C::Engine as WasmEngine>::Instance as WasmInstance<
1128 C::Engine,
1129 >>::new(
1130 ctx.as_context_mut().inner,
1131 module.module.cast(),
1132 &backend_imports,
1133 )?),
1134 })
1135 }
1136
1137 pub fn exports<C: AsContext>(&self, ctx: C) -> impl Iterator<Item = Export> {
1139 let instance = self.instance.cast::<<C::Engine as WasmEngine>::Instance>();
1140
1141 <_ as WasmInstance<_>>::exports(instance, ctx.as_context().inner).map(Into::into)
1142 }
1143
1144 pub fn get_export<C: AsContext>(&self, ctx: C, name: &str) -> Option<Extern> {
1146 let instance = self.instance.cast::<<C::Engine as WasmEngine>::Instance>();
1147
1148 <_ as WasmInstance<_>>::get_export(instance, ctx.as_context().inner, name)
1149 .as_ref()
1150 .map(Into::into)
1151 }
1152}
1153
1154#[derive(Clone, Debug)]
1156pub struct Memory {
1157 memory: BackendObject,
1159}
1160
1161impl Memory {
1162 pub fn new<C: AsContextMut>(mut ctx: C, ty: MemoryType) -> Result<Self> {
1164 Ok(Self {
1165 memory: BackendObject::new(<<C::Engine as WasmEngine>::Memory as WasmMemory<
1166 C::Engine,
1167 >>::new(ctx.as_context_mut().inner, ty)?),
1168 })
1169 }
1170
1171 pub fn ty<C: AsContext>(&self, ctx: C) -> MemoryType {
1173 self.memory
1174 .cast::<<C::Engine as WasmEngine>::Memory>()
1175 .ty(ctx.as_context().inner)
1176 }
1177
1178 pub fn grow<C: AsContextMut>(&self, mut ctx: C, additional: u32) -> Result<u32> {
1180 self.memory
1181 .cast::<<C::Engine as WasmEngine>::Memory>()
1182 .grow(ctx.as_context_mut().inner, additional)
1183 }
1184
1185 pub fn current_pages<C: AsContext>(&self, ctx: C) -> u32 {
1187 self.memory
1188 .cast::<<C::Engine as WasmEngine>::Memory>()
1189 .current_pages(ctx.as_context().inner)
1190 }
1191
1192 pub fn read<C: AsContext>(&self, ctx: C, offset: usize, buffer: &mut [u8]) -> Result<()> {
1195 self.memory
1196 .cast::<<C::Engine as WasmEngine>::Memory>()
1197 .read(ctx.as_context().inner, offset, buffer)
1198 }
1199
1200 pub fn write<C: AsContextMut>(&self, mut ctx: C, offset: usize, buffer: &[u8]) -> Result<()> {
1203 self.memory
1204 .cast::<<C::Engine as WasmEngine>::Memory>()
1205 .write(ctx.as_context_mut().inner, offset, buffer)
1206 }
1207}
1208
1209#[derive(Clone, Debug)]
1211pub struct Table {
1212 table: BackendObject,
1214}
1215
1216impl Table {
1217 pub fn new<C: AsContextMut>(mut ctx: C, ty: TableType, init: Value) -> Result<Self> {
1219 Ok(Self {
1220 table: BackendObject::new(<<C::Engine as WasmEngine>::Table as WasmTable<
1221 C::Engine,
1222 >>::new(
1223 ctx.as_context_mut().inner, ty, (&init).into()
1224 )?),
1225 })
1226 }
1227
1228 pub fn ty<C: AsContext>(&self, ctx: C) -> TableType {
1230 self.table
1231 .cast::<<C::Engine as WasmEngine>::Table>()
1232 .ty(ctx.as_context().inner)
1233 }
1234
1235 pub fn size<C: AsContext>(&self, ctx: C) -> u32 {
1237 self.table
1238 .cast::<<C::Engine as WasmEngine>::Table>()
1239 .size(ctx.as_context().inner)
1240 }
1241
1242 pub fn grow<C: AsContextMut>(&self, mut ctx: C, delta: u32, init: Value) -> Result<u32> {
1246 let table = self.table.cast::<<C::Engine as WasmEngine>::Table>();
1247
1248 <_ as WasmTable<_>>::grow(table, ctx.as_context_mut().inner, delta, (&init).into())
1249 }
1250
1251 pub fn get<C: AsContextMut>(&self, mut ctx: C, index: u32) -> Option<Value> {
1255 let table = self.table.cast::<<C::Engine as WasmEngine>::Table>();
1256
1257 <_ as WasmTable<_>>::get(table, ctx.as_context_mut().inner, index)
1258 .as_ref()
1259 .map(Into::into)
1260 }
1261
1262 pub fn set<C: AsContextMut>(&self, mut ctx: C, index: u32, value: Value) -> Result<()> {
1264 let table = self.table.cast::<<C::Engine as WasmEngine>::Table>();
1265
1266 <_ as WasmTable<_>>::set(table, ctx.as_context_mut().inner, index, (&value).into())
1267 }
1268}
1269
1270struct BackendObject {
1272 inner: Box<dyn AnyCloneBoxed>,
1274}
1275
1276impl BackendObject {
1277 pub fn new<T: 'static + Clone + Send + Sync>(value: T) -> Self {
1279 Self {
1280 inner: Box::new(value),
1281 }
1282 }
1283
1284 pub fn cast<T: 'static>(&self) -> &T {
1286 self.inner
1287 .as_any()
1288 .downcast_ref()
1289 .expect("Attempted to use incorrect context to access function.")
1290 }
1291}
1292
1293impl Clone for BackendObject {
1294 fn clone(&self) -> Self {
1295 Self {
1296 inner: self.inner.clone_boxed(),
1297 }
1298 }
1299}
1300
1301impl fmt::Debug for BackendObject {
1302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1303 f.debug_struct("BackendObject").finish()
1304 }
1305}
1306
1307trait AnyCloneBoxed: Any + Send + Sync {
1309 fn as_any(&self) -> &(dyn Any + Send + Sync);
1311
1312 fn clone_boxed(&self) -> Box<dyn AnyCloneBoxed>;
1314}
1315
1316impl<T: Any + Clone + Send + Sync> AnyCloneBoxed for T {
1317 fn as_any(&self) -> &(dyn Any + Send + Sync) {
1318 self
1319 }
1320
1321 fn clone_boxed(&self) -> Box<dyn AnyCloneBoxed> {
1322 Box::new(self.clone())
1323 }
1324}
1325
1326pub trait AsContext {
1328 type Engine: WasmEngine;
1330
1331 type UserState: 'static;
1333
1334 fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine>;
1336}
1337
1338pub trait AsContextMut: AsContext {
1340 fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine>;
1342}
1343
1344impl<T: 'static, E: WasmEngine> AsContext for Store<T, E> {
1345 type Engine = E;
1346
1347 type UserState = T;
1348
1349 fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
1350 StoreContext {
1351 inner: crate::backend::AsContext::as_context(&self.inner),
1352 }
1353 }
1354}
1355
1356impl<T: 'static, E: WasmEngine> AsContextMut for Store<T, E> {
1357 fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine> {
1358 StoreContextMut {
1359 inner: crate::backend::AsContextMut::as_context_mut(&mut self.inner),
1360 }
1361 }
1362}
1363
1364impl<T: AsContext> AsContext for &T {
1365 type Engine = T::Engine;
1366
1367 type UserState = T::UserState;
1368
1369 fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
1370 (**self).as_context()
1371 }
1372}
1373
1374impl<T: AsContext> AsContext for &mut T {
1375 type Engine = T::Engine;
1376
1377 type UserState = T::UserState;
1378
1379 fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
1380 (**self).as_context()
1381 }
1382}
1383
1384impl<T: AsContextMut> AsContextMut for &mut T {
1385 fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine> {
1386 (**self).as_context_mut()
1387 }
1388}
1389
1390impl<'a, T: 'static, E: WasmEngine> AsContext for StoreContext<'a, T, E> {
1391 type Engine = E;
1392
1393 type UserState = T;
1394
1395 fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
1396 StoreContext {
1397 inner: crate::backend::AsContext::as_context(&self.inner),
1398 }
1399 }
1400}
1401
1402impl<'a, T: 'static, E: WasmEngine> AsContext for StoreContextMut<'a, T, E> {
1403 type Engine = E;
1404
1405 type UserState = T;
1406
1407 fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
1408 StoreContext {
1409 inner: crate::backend::AsContext::as_context(&self.inner),
1410 }
1411 }
1412}
1413
1414impl<'a, T: 'static, E: WasmEngine> AsContextMut for StoreContextMut<'a, T, E> {
1415 fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine> {
1416 StoreContextMut {
1417 inner: crate::backend::AsContextMut::as_context_mut(&mut self.inner),
1418 }
1419 }
1420}