1use core::num::NonZeroU32;
25
26use crate::{
27 addrs::{FuncAddr, GlobalAddr, MemAddr, ModuleAddr, TableAddr},
28 config::Config,
29 core::reader::types::{FuncType, MemType, TableType},
30 linker::Linker,
31 resumable::{ResumableRef, RunState},
32 ExternVal, GlobalType, InstantiationOutcome, RuntimeError, Store, StoreId, ValidationInfo,
33};
34use alloc::{string::String, vec::Vec};
35
36mod interop;
37mod value;
38
39pub use interop::*;
40pub use value::*;
41
42impl<'b, T: Config> Store<'b, T> {
51 pub fn module_instantiate(
56 &mut self,
57 validation_info: &ValidationInfo<'b>,
58 extern_vals: Vec<StoredExternVal>,
59 maybe_fuel: Option<u32>,
60 ) -> Result<StoredInstantiationOutcome, RuntimeError> {
61 let extern_vals = extern_vals
63 .into_iter()
64 .map(|extern_val| extern_val.try_unwrap_into_bare(self.id))
65 .collect::<Result<Vec<ExternVal>, RuntimeError>>()?;
66 let instantiation_outcome =
68 self.module_instantiate_unchecked(validation_info, extern_vals, maybe_fuel)?;
69 let stored_instantiation_outcome =
72 unsafe { StoredInstantiationOutcome::from_bare(instantiation_outcome, self.id) };
73 Ok(stored_instantiation_outcome)
75 }
76
77 pub fn instance_export(
79 &self,
80 module_addr: Stored<ModuleAddr>,
81 name: &str,
82 ) -> Result<StoredExternVal, RuntimeError> {
83 let module_addr = module_addr.try_unwrap_into_bare(self.id)?;
85 let extern_val = self.instance_export_unchecked(module_addr, name)?;
87 let stored_extern_val = unsafe { StoredExternVal::from_bare(extern_val, self.id) };
90 Ok(stored_extern_val)
92 }
93
94 pub fn func_type(&self, func_addr: Stored<FuncAddr>) -> Result<FuncType, RuntimeError> {
99 let func_addr = func_addr.try_unwrap_into_bare(self.id)?;
101 let func_type = self.func_type_unchecked(func_addr);
103 Ok(func_type)
107 }
108
109 pub fn invoke(
111 &mut self,
112 func_addr: Stored<FuncAddr>,
113 params: Vec<StoredValue>,
114 maybe_fuel: Option<u32>,
115 ) -> Result<StoredRunState, RuntimeError> {
116 let func_addr = func_addr.try_unwrap_into_bare(self.id)?;
118 let params = try_unwrap_values(params, self.id)?;
119 let run_state = self.invoke_unchecked(func_addr, params, maybe_fuel)?;
121 let stored_run_state = unsafe { StoredRunState::from_bare(run_state, self.id) };
124 Ok(stored_run_state)
126 }
127
128 pub fn table_alloc(
130 &mut self,
131 table_type: TableType,
132 r#ref: StoredRef,
133 ) -> Result<Stored<TableAddr>, RuntimeError> {
134 let r#ref = r#ref.try_unwrap_into_bare(self.id)?;
136 let table_addr = self.table_alloc_unchecked(table_type, r#ref)?;
138 let stored_table_addr = unsafe { Stored::from_bare(table_addr, self.id) };
141 Ok(stored_table_addr)
143 }
144
145 pub fn table_type(&self, table_addr: Stored<TableAddr>) -> Result<TableType, RuntimeError> {
147 let table_addr = table_addr.try_unwrap_into_bare(self.id)?;
149 let table_type = self.table_type_unchecked(table_addr);
151 Ok(table_type)
155 }
156
157 pub fn table_read(
159 &self,
160 table_addr: Stored<TableAddr>,
161 i: u32,
162 ) -> Result<StoredRef, RuntimeError> {
163 let table_addr = table_addr.try_unwrap_into_bare(self.id)?;
165 let r#ref = self.table_read_unchecked(table_addr, i)?;
167 let stored_ref = unsafe { StoredRef::from_bare(r#ref, self.id) };
170 Ok(stored_ref)
172 }
173
174 pub fn table_write(
176 &mut self,
177 table_addr: Stored<TableAddr>,
178 i: u32,
179 r#ref: StoredRef,
180 ) -> Result<(), RuntimeError> {
181 let table_addr = table_addr.try_unwrap_into_bare(self.id)?;
183 let r#ref = r#ref.try_unwrap_into_bare(self.id)?;
184 self.table_write_unchecked(table_addr, i, r#ref)?;
186 Ok(())
190 }
191
192 pub fn table_size(&self, table_addr: Stored<TableAddr>) -> Result<u32, RuntimeError> {
194 let table_addr = table_addr.try_unwrap_into_bare(self.id)?;
196 let table_size = self.table_size_unchecked(table_addr);
198 Ok(table_size)
202 }
203
204 #[allow(clippy::let_and_return)] pub fn mem_alloc(&mut self, mem_type: MemType) -> Stored<MemAddr> {
207 let mem_addr = self.mem_alloc_unchecked(mem_type);
211 let stored_mem_addr = unsafe { Stored::from_bare(mem_addr, self.id) };
214 stored_mem_addr
216 }
217
218 pub fn mem_type(&self, mem_addr: Stored<MemAddr>) -> Result<MemType, RuntimeError> {
220 let mem_addr = mem_addr.try_unwrap_into_bare(self.id)?;
222 let mem_type = self.mem_type_unchecked(mem_addr);
224 Ok(mem_type)
228 }
229
230 pub fn mem_read(&self, mem_addr: Stored<MemAddr>, i: u32) -> Result<u8, RuntimeError> {
232 let mem_addr = mem_addr.try_unwrap_into_bare(self.id)?;
234 let byte = self.mem_read_unchecked(mem_addr, i)?;
236 Ok(byte)
240 }
241
242 pub fn mem_write(
244 &mut self,
245 mem_addr: Stored<MemAddr>,
246 i: u32,
247 byte: u8,
248 ) -> Result<(), RuntimeError> {
249 let mem_addr = mem_addr.try_unwrap_into_bare(self.id)?;
251 self.mem_write_unchecked(mem_addr, i, byte)?;
253 Ok(())
257 }
258
259 pub fn mem_size(&self, mem_addr: Stored<MemAddr>) -> Result<u32, RuntimeError> {
261 let mem_addr = mem_addr.try_unwrap_into_bare(self.id)?;
263 let mem_size = self.mem_size_unchecked(mem_addr);
265 Ok(mem_size)
269 }
270
271 pub fn mem_grow(&mut self, mem_addr: Stored<MemAddr>, n: u32) -> Result<(), RuntimeError> {
273 let mem_addr = mem_addr.try_unwrap_into_bare(self.id)?;
275 self.mem_grow_unchecked(mem_addr, n)?;
277 Ok(())
281 }
282
283 pub fn global_alloc(
285 &mut self,
286 global_type: GlobalType,
287 val: StoredValue,
288 ) -> Result<Stored<GlobalAddr>, RuntimeError> {
289 let val = val.try_unwrap_into_bare(self.id)?;
291 let global_addr = self.global_alloc_unchecked(global_type, val)?;
293 let stored_global_addr = unsafe { Stored::from_bare(global_addr, self.id) };
296 Ok(stored_global_addr)
298 }
299
300 pub fn global_type(&self, global_addr: Stored<GlobalAddr>) -> Result<GlobalType, RuntimeError> {
302 let global_addr = global_addr.try_unwrap_into_bare(self.id)?;
304 let global_type = self.global_type_unchecked(global_addr);
306 Ok(global_type)
310 }
311
312 pub fn global_read(
314 &self,
315 global_addr: Stored<GlobalAddr>,
316 ) -> Result<StoredValue, RuntimeError> {
317 let global_addr = global_addr.try_unwrap_into_bare(self.id)?;
319 let value = self.global_read_unchecked(global_addr);
321 let stored_value = unsafe { StoredValue::from_bare(value, self.id) };
324 Ok(stored_value)
326 }
327
328 pub fn global_write(
330 &mut self,
331 global_addr: Stored<GlobalAddr>,
332 val: StoredValue,
333 ) -> Result<(), RuntimeError> {
334 let global_addr = global_addr.try_unwrap_into_bare(self.id)?;
336 let val = val.try_unwrap_into_bare(self.id)?;
337 self.global_write_unchecked(global_addr, val)?;
339 Ok(())
343 }
344
345 pub fn create_resumable(
347 &self,
348 func_addr: Stored<FuncAddr>,
349 params: Vec<StoredValue>,
350 maybe_fuel: Option<u32>,
351 ) -> Result<Stored<ResumableRef>, RuntimeError> {
352 let func_addr = func_addr.try_unwrap_into_bare(self.id)?;
354 let params = try_unwrap_values(params, self.id)?;
355 let resumable_ref = self.create_resumable_unchecked(func_addr, params, maybe_fuel)?;
357 let stored_resumable_ref = unsafe { Stored::from_bare(resumable_ref, self.id) };
360 Ok(stored_resumable_ref)
362 }
363
364 pub fn resume(
366 &mut self,
367 resumable_ref: Stored<ResumableRef>,
368 ) -> Result<StoredRunState, RuntimeError> {
369 let resumable_ref = resumable_ref.try_unwrap_into_bare(self.id)?;
371 let run_state = self.resume_unchecked(resumable_ref)?;
373 let stored_run_state = unsafe { StoredRunState::from_bare(run_state, self.id) };
376 Ok(stored_run_state)
378 }
379
380 pub fn access_fuel_mut<R>(
384 &mut self,
385 resumable_ref: &mut Stored<ResumableRef>,
386 f: impl FnOnce(&mut Option<u32>) -> R,
387 ) -> Result<R, RuntimeError> {
388 let resumable_ref = resumable_ref.as_mut().try_unwrap_into_bare(self.id)?;
390 let r = self.access_fuel_mut_unchecked(resumable_ref, f)?;
392 Ok(r)
396 }
397
398 pub fn invoke_without_fuel(
403 &mut self,
404 func_addr: Stored<FuncAddr>,
405 params: Vec<StoredValue>,
406 ) -> Result<Vec<StoredValue>, RuntimeError> {
407 let func_addr = func_addr.try_unwrap_into_bare(self.id)?;
409 let params = try_unwrap_values(params, self.id)?;
410 let returns = self.invoke_without_fuel_unchecked(func_addr, params)?;
412 let returns = unsafe { wrap_vec_elements(returns, self.id) };
415 Ok(returns)
417 }
418
419 pub fn invoke_typed_without_fuel<
421 Params: StoredInteropValueList,
422 Returns: StoredInteropValueList,
423 >(
424 &mut self,
425 function: Stored<FuncAddr>,
426 params: Params,
427 ) -> Result<Returns, RuntimeError> {
428 let function = function.try_unwrap_into_bare(self.id)?;
430 let params = try_unwrap_values(params.into_values(), self.id)?;
431 let returns = self.invoke_without_fuel_unchecked(function, params)?;
433 let stored_returns = unsafe { wrap_vec_elements(returns, self.id) };
436 let stored_returns = Returns::try_from_values(stored_returns.into_iter())
438 .map_err(|_| RuntimeError::FunctionInvocationSignatureMismatch)?;
439 Ok(stored_returns)
440 }
441}
442
443impl Linker {
454 pub fn define(
456 &mut self,
457 module_name: String,
458 name: String,
459 extern_val: StoredExternVal,
460 ) -> Result<(), RuntimeError> {
461 let extern_val_store_id = extern_val
463 .id()
464 .expect("this type to always contain a StoreId");
465 let linker_store_id = *self.store_id.get_or_insert(extern_val_store_id);
466 if linker_store_id != extern_val_store_id {
467 return Err(RuntimeError::StoreIdMismatch);
468 }
469 let extern_val = extern_val.try_unwrap_into_bare(linker_store_id)?;
471 self.define_unchecked(module_name, name, extern_val)?;
473 Ok(())
477 }
478
479 pub fn define_module_instance<T: Config>(
481 &mut self,
482 store: &Store<T>,
483 module_name: String,
484 module: Stored<ModuleAddr>,
485 ) -> Result<(), RuntimeError> {
486 let module_store_id = module.id().expect("this type to always contain a StoreId");
488 let linker_store_id = *self.store_id.get_or_insert(module_store_id);
489 if linker_store_id != module_store_id {
490 return Err(RuntimeError::StoreIdMismatch);
491 }
492 let module = module.try_unwrap_into_bare(linker_store_id)?;
494 self.define_module_instance_unchecked(store, module_name, module)?;
496 Ok(())
500 }
501
502 pub fn get(&self, module_name: String, name: String) -> Result<StoredExternVal, RuntimeError> {
521 let Some(linker_store_id) = self.store_id else {
524 return Err(RuntimeError::LinkerNotYetAssociatedWithStoreId);
537 };
538 let extern_val = self
542 .get_unchecked(module_name, name)
543 .ok_or(RuntimeError::UnableToResolveExternLookup)?;
544 let stored_extern_val = unsafe { StoredExternVal::from_bare(extern_val, linker_store_id) };
549 Ok(stored_extern_val)
551 }
552
553 pub fn instantiate_pre(
564 &self,
565 validation_info: &ValidationInfo,
566 ) -> Result<Vec<StoredExternVal>, RuntimeError> {
567 if validation_info.imports.is_empty() {
572 return Ok(Vec::new());
573 }
574 let Some(linker_store_id) = self.store_id else {
576 return Err(RuntimeError::LinkerNotYetAssociatedWithStoreId);
579 };
580 let extern_vals = self.instantiate_pre_unchecked(validation_info)?;
584 let stored_extern_vals = unsafe { wrap_vec_elements(extern_vals, linker_store_id) };
589 Ok(stored_extern_vals)
591 }
592
593 pub fn module_instantiate<'b, T: Config>(
595 &mut self,
596 store: &mut Store<'b, T>,
597 validation_info: &ValidationInfo<'b>,
598 maybe_fuel: Option<u32>,
599 ) -> Result<StoredInstantiationOutcome, RuntimeError> {
600 let linker_store_id = *self.store_id.get_or_insert(store.id);
602 if linker_store_id != store.id {
603 return Err(RuntimeError::StoreIdMismatch);
604 }
605 let instantiation_outcome =
609 self.module_instantiate_unchecked(store, validation_info, maybe_fuel)?;
610 let stored_instantiation_outcome = unsafe {
616 StoredInstantiationOutcome::from_bare(instantiation_outcome, linker_store_id)
617 };
618 Ok(stored_instantiation_outcome)
620 }
621}
622
623trait AbstractStored: Sized {
626 type BareTy: Sized;
627
628 unsafe fn from_bare(bare_value: Self::BareTy, id: StoreId) -> Self;
634
635 fn id(&self) -> Option<StoreId>;
639
640 fn into_bare(self) -> Self::BareTy;
642
643 fn try_unwrap_into_bare(
650 self,
651 expected_store_id: StoreId,
652 ) -> Result<Self::BareTy, RuntimeError> {
653 if let Some(id) = self.id() {
654 if id != expected_store_id {
655 return Err(RuntimeError::StoreIdMismatch);
656 }
657 }
658
659 Ok(self.into_bare())
660 }
661}
662
663pub struct Stored<T> {
666 id: StoreId,
667 inner: T,
668}
669
670impl<T> AbstractStored for Stored<T> {
671 type BareTy = T;
672
673 unsafe fn from_bare(bare_value: Self::BareTy, id: StoreId) -> Self {
674 Self {
675 inner: bare_value,
676 id,
677 }
678 }
679
680 fn id(&self) -> Option<StoreId> {
681 Some(self.id)
682 }
683
684 fn into_bare(self) -> Self::BareTy {
685 self.inner
686 }
687}
688
689impl<T: Clone> Clone for Stored<T> {
690 fn clone(&self) -> Self {
691 Self {
692 id: self.id,
693 inner: self.inner.clone(),
694 }
695 }
696}
697
698impl<T: Copy> Copy for Stored<T> {}
699
700impl<T: core::fmt::Debug> core::fmt::Debug for Stored<T> {
701 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
702 f.debug_struct("Stored")
703 .field("inner", &self)
704 .field("id", &self.id)
705 .finish()
706 }
707}
708
709impl<T: PartialEq> PartialEq for Stored<T> {
710 fn eq(&self, other: &Self) -> bool {
711 self.id.eq(&other.id) && self.inner.eq(&other.inner)
712 }
713}
714
715impl<T: Eq> Eq for Stored<T> {}
716
717impl<T> Stored<T> {
718 fn as_mut(&mut self) -> Stored<&mut T> {
722 Stored {
723 id: self.id,
724 inner: &mut self.inner,
725 }
726 }
727}
728
729#[derive(Debug, Copy, Clone, PartialEq, Eq)]
731pub enum StoredExternVal {
732 Func(Stored<FuncAddr>),
733 Table(Stored<TableAddr>),
734 Mem(Stored<MemAddr>),
735 Global(Stored<GlobalAddr>),
736}
737
738impl AbstractStored for StoredExternVal {
739 type BareTy = ExternVal;
740
741 unsafe fn from_bare(bare_value: Self::BareTy, id: StoreId) -> Self {
742 match bare_value {
743 ExternVal::Func(func_addr) => Self::Func(Stored::from_bare(func_addr, id)),
744 ExternVal::Table(table_addr) => Self::Table(Stored::from_bare(table_addr, id)),
745 ExternVal::Mem(mem_addr) => Self::Mem(Stored::from_bare(mem_addr, id)),
746 ExternVal::Global(global_addr) => Self::Global(Stored::from_bare(global_addr, id)),
747 }
748 }
749
750 fn id(&self) -> Option<StoreId> {
751 match self {
752 StoredExternVal::Func(stored_func_addr) => stored_func_addr.id(),
753 StoredExternVal::Table(stored_table_addr) => stored_table_addr.id(),
754 StoredExternVal::Mem(stored_mem_addr) => stored_mem_addr.id(),
755 StoredExternVal::Global(stored_global_addr) => stored_global_addr.id(),
756 }
757 }
758
759 fn into_bare(self) -> Self::BareTy {
760 match self {
761 StoredExternVal::Func(stored_func_addr) => {
762 ExternVal::Func(stored_func_addr.into_bare())
763 }
764 StoredExternVal::Table(stored_table_addr) => {
765 ExternVal::Table(stored_table_addr.into_bare())
766 }
767 StoredExternVal::Mem(stored_mem_addr) => ExternVal::Mem(stored_mem_addr.into_bare()),
768 StoredExternVal::Global(stored_global_addr) => {
769 ExternVal::Global(stored_global_addr.into_bare())
770 }
771 }
772 }
773}
774
775impl StoredExternVal {
776 pub fn as_func(self) -> Option<Stored<FuncAddr>> {
777 match self {
778 StoredExternVal::Func(func_addr) => Some(func_addr),
779 _ => None,
780 }
781 }
782
783 pub fn as_table(self) -> Option<Stored<TableAddr>> {
784 match self {
785 StoredExternVal::Table(table_addr) => Some(table_addr),
786 _ => None,
787 }
788 }
789
790 pub fn as_mem(self) -> Option<Stored<MemAddr>> {
791 match self {
792 StoredExternVal::Mem(mem_addr) => Some(mem_addr),
793 _ => None,
794 }
795 }
796
797 pub fn as_global(self) -> Option<Stored<GlobalAddr>> {
798 match self {
799 StoredExternVal::Global(global_addr) => Some(global_addr),
800 _ => None,
801 }
802 }
803}
804
805pub enum StoredRunState {
807 Finished {
808 values: Vec<StoredValue>,
809 maybe_remaining_fuel: Option<u32>,
810 },
811 Resumable {
812 resumable_ref: Stored<ResumableRef>,
813 required_fuel: NonZeroU32,
814 },
815}
816
817impl AbstractStored for StoredRunState {
818 type BareTy = RunState;
819
820 unsafe fn from_bare(bare_value: Self::BareTy, id: StoreId) -> Self {
821 match bare_value {
822 RunState::Finished {
823 values,
824 maybe_remaining_fuel,
825 } => Self::Finished {
826 values: wrap_vec_elements(values, id),
827 maybe_remaining_fuel,
828 },
829 RunState::Resumable {
830 resumable_ref,
831 required_fuel,
832 } => Self::Resumable {
833 resumable_ref: Stored::from_bare(resumable_ref, id),
834 required_fuel,
835 },
836 }
837 }
838
839 fn id(&self) -> Option<StoreId> {
840 todo!()
841 }
842
843 fn into_bare(self) -> Self::BareTy {
844 todo!()
845 }
846}
847
848pub struct StoredInstantiationOutcome {
850 pub module_addr: Stored<ModuleAddr>,
851 pub maybe_remaining_fuel: Option<u32>,
852}
853
854impl AbstractStored for StoredInstantiationOutcome {
855 type BareTy = InstantiationOutcome;
856
857 unsafe fn from_bare(bare_value: Self::BareTy, id: StoreId) -> Self {
858 Self {
859 module_addr: Stored::from_bare(bare_value.module_addr, id),
860 maybe_remaining_fuel: bare_value.maybe_remaining_fuel,
861 }
862 }
863
864 fn id(&self) -> Option<StoreId> {
865 self.module_addr.id()
866 }
867
868 fn into_bare(self) -> Self::BareTy {
869 InstantiationOutcome {
870 module_addr: self.module_addr.into_bare(),
871 maybe_remaining_fuel: self.maybe_remaining_fuel,
872 }
873 }
874}
875
876unsafe fn wrap_vec_elements<S: AbstractStored>(values: Vec<S::BareTy>, id: StoreId) -> Vec<S> {
883 values
884 .into_iter()
885 .map(|value| {
886 unsafe { S::from_bare(value, id) }
890 })
891 .collect()
892}
893
894fn try_unwrap_values<S: AbstractStored>(
901 stored_values: Vec<S>,
902 expected_store_id: StoreId,
903) -> Result<Vec<S::BareTy>, RuntimeError> {
904 stored_values
905 .into_iter()
906 .map(|stored_value| stored_value.try_unwrap_into_bare(expected_store_id))
907 .collect()
908}