1use crate::{
2 collections::{
3 string_interner::{InternHint, Sym as Symbol},
4 StringInterner,
5 },
6 func::{FuncEntity, HostFuncEntity, HostFuncTrampolineEntity},
7 module::{ImportName, ImportType},
8 AsContext,
9 AsContextMut,
10 Caller,
11 Engine,
12 Error,
13 Extern,
14 ExternType,
15 Func,
16 FuncType,
17 GlobalType,
18 InstancePre,
19 IntoFunc,
20 MemoryType,
21 Module,
22 TableType,
23 Val,
24};
25use core::{
26 fmt::{self, Debug, Display},
27 marker::PhantomData,
28};
29use std::{
30 collections::{btree_map::Entry, BTreeMap},
31 sync::Arc,
32 vec::Vec,
33};
34
35#[derive(Debug)]
37pub enum LinkerError {
38 DuplicateDefinition {
40 import_name: ImportName,
42 },
43 MissingDefinition {
45 name: ImportName,
47 ty: ExternType,
49 },
50 InvalidTypeDefinition {
52 name: ImportName,
54 expected: ExternType,
56 found: ExternType,
58 },
59 FuncTypeMismatch {
61 name: ImportName,
63 expected: FuncType,
65 found: FuncType,
67 },
68 InvalidTableSubtype {
70 name: ImportName,
72 ty: TableType,
74 other: TableType,
76 },
77 InvalidMemorySubtype {
79 name: ImportName,
81 ty: MemoryType,
83 other: MemoryType,
85 },
86 GlobalTypeMismatch {
88 name: ImportName,
90 expected: GlobalType,
92 found: GlobalType,
94 },
95}
96
97impl LinkerError {
98 fn missing_definition(import: &ImportType) -> Self {
100 Self::MissingDefinition {
101 name: import.import_name().clone(),
102 ty: import.ty().clone(),
103 }
104 }
105
106 fn invalid_type_definition(import: &ImportType, found: &ExternType) -> Self {
108 Self::InvalidTypeDefinition {
109 name: import.import_name().clone(),
110 expected: import.ty().clone(),
111 found: found.clone(),
112 }
113 }
114
115 fn func_type_mismatch(name: &ImportName, expected: &FuncType, found: &FuncType) -> Self {
117 Self::FuncTypeMismatch {
118 name: name.clone(),
119 expected: expected.clone(),
120 found: found.clone(),
121 }
122 }
123
124 fn table_type_mismatch(name: &ImportName, ty: &TableType, other: &TableType) -> Self {
126 Self::InvalidTableSubtype {
127 name: name.clone(),
128 ty: *ty,
129 other: *other,
130 }
131 }
132
133 fn invalid_memory_subtype(name: &ImportName, ty: &MemoryType, other: &MemoryType) -> Self {
135 Self::InvalidMemorySubtype {
136 name: name.clone(),
137 ty: *ty,
138 other: *other,
139 }
140 }
141
142 fn global_type_mismatch(name: &ImportName, expected: &GlobalType, found: &GlobalType) -> Self {
144 Self::GlobalTypeMismatch {
145 name: name.clone(),
146 expected: *expected,
147 found: *found,
148 }
149 }
150}
151
152#[cfg(feature = "std")]
153impl std::error::Error for LinkerError {}
154
155impl Display for LinkerError {
156 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157 match self {
158 Self::DuplicateDefinition { import_name } => {
159 write!(
160 f,
161 "encountered duplicate definition with name `{import_name}`",
162 )
163 }
164 Self::MissingDefinition { name, ty } => {
165 write!(
166 f,
167 "cannot find definition for import {name} with type {ty:?}",
168 )
169 }
170 Self::InvalidTypeDefinition {
171 name,
172 expected,
173 found,
174 } => {
175 write!(f, "found definition for import {name} with type {expected:?} but found type {found:?}")
176 }
177 Self::FuncTypeMismatch {
178 name,
179 expected,
180 found,
181 } => {
182 write!(
183 f,
184 "function type mismatch for import {name}: \
185 expected {expected:?} but found {found:?}",
186 )
187 }
188 Self::InvalidTableSubtype { name, ty, other } => {
189 write!(
190 f,
191 "import {name}: table type {ty:?} is not a subtype of {other:?}"
192 )
193 }
194 Self::InvalidMemorySubtype { name, ty, other } => {
195 write!(
196 f,
197 "import {name}: memory type {ty:?} is not a subtype of {other:?}"
198 )
199 }
200 Self::GlobalTypeMismatch {
201 name,
202 expected,
203 found,
204 } => {
205 write!(
206 f,
207 "global variable type mismatch for import {name}: \
208 expected {expected:?} but found {found:?}",
209 )
210 }
211 }
212 }
213}
214
215#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
217#[repr(transparent)]
218struct ImportKey {
219 module_and_name: u64,
223}
224
225impl Debug for ImportKey {
226 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227 f.debug_struct("ImportKey")
228 .field("module", &self.module())
229 .field("name", &self.name())
230 .finish()
231 }
232}
233
234impl ImportKey {
235 #[inline]
237 pub fn new(module: Symbol, name: Symbol) -> Self {
238 let module_and_name = u64::from(module.into_u32()) << 32 | u64::from(name.into_u32());
239 Self { module_and_name }
240 }
241
242 #[inline]
244 pub fn module(&self) -> Symbol {
245 Symbol::from_u32((self.module_and_name >> 32) as u32)
246 }
247
248 #[inline]
250 pub fn name(&self) -> Symbol {
251 Symbol::from_u32(self.module_and_name as u32)
252 }
253}
254
255#[derive(Debug)]
257enum Definition<T> {
258 Extern(Extern),
260 HostFunc(HostFuncTrampolineEntity<T>),
262}
263
264impl<T> Clone for Definition<T> {
265 fn clone(&self) -> Self {
266 match self {
267 Self::Extern(definition) => Self::Extern(*definition),
268 Self::HostFunc(host_func) => Self::HostFunc(host_func.clone()),
269 }
270 }
271}
272
273impl<T> Definition<T> {
274 fn as_extern(&self) -> Option<&Extern> {
278 match self {
279 Definition::Extern(item) => Some(item),
280 Definition::HostFunc(_) => None,
281 }
282 }
283
284 pub fn ty(&self, ctx: impl AsContext) -> ExternType {
286 match self {
287 Definition::Extern(item) => item.ty(ctx),
288 Definition::HostFunc(host_func) => ExternType::Func(host_func.func_type().clone()),
289 }
290 }
291
292 pub fn as_func(&self, mut ctx: impl AsContextMut<Data = T>) -> Option<Func> {
303 match self {
304 Definition::Extern(Extern::Func(func)) => Some(*func),
305 Definition::HostFunc(host_func) => {
306 let trampoline = ctx
307 .as_context_mut()
308 .store
309 .alloc_trampoline(host_func.trampoline().clone());
310 let ty = host_func.func_type();
311 let entity = HostFuncEntity::new(ctx.as_context().engine(), ty, trampoline);
312 let func = ctx
313 .as_context_mut()
314 .store
315 .inner
316 .alloc_func(FuncEntity::Host(entity));
317 Some(func)
318 }
319 _ => None,
320 }
321 }
322}
323
324#[derive(Debug)]
326pub struct Linker<T> {
327 engine: Engine,
334 shared: Option<Arc<LinkerInner<T>>>,
338 inner: LinkerInner<T>,
340}
341
342impl<T> Clone for Linker<T> {
343 fn clone(&self) -> Linker<T> {
344 Self {
345 engine: self.engine.clone(),
346 shared: self.shared.clone(),
347 inner: self.inner.clone(),
348 }
349 }
350}
351
352impl<T> Default for Linker<T> {
353 fn default() -> Self {
354 Self::new(&Engine::default())
355 }
356}
357
358impl<T> Linker<T> {
359 pub fn new(engine: &Engine) -> Self {
361 Self {
362 engine: engine.clone(),
363 shared: None,
364 inner: LinkerInner::default(),
365 }
366 }
367
368 pub fn build() -> LinkerBuilder<state::Constructing, T> {
370 LinkerBuilder {
371 inner: Arc::new(LinkerInner::default()),
372 marker: PhantomData,
373 }
374 }
375
376 pub fn engine(&self) -> &Engine {
378 &self.engine
379 }
380
381 fn ensure_undefined(&self, module: &str, name: &str) -> Result<(), LinkerError> {
389 if let Some(shared) = &self.shared {
390 if shared.has_definition(module, name) {
391 return Err(LinkerError::DuplicateDefinition {
392 import_name: ImportName::new(module, name),
393 });
394 }
395 }
396 Ok(())
397 }
398
399 pub fn define(
405 &mut self,
406 module: &str,
407 name: &str,
408 item: impl Into<Extern>,
409 ) -> Result<&mut Self, LinkerError> {
410 self.ensure_undefined(module, name)?;
411 let key = self.inner.new_import_key(module, name);
412 self.inner.insert(key, Definition::Extern(item.into()))?;
413 Ok(self)
414 }
415
416 pub fn func_new(
424 &mut self,
425 module: &str,
426 name: &str,
427 ty: FuncType,
428 func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
429 ) -> Result<&mut Self, LinkerError> {
430 self.ensure_undefined(module, name)?;
431 let func = HostFuncTrampolineEntity::new(ty, func);
432 let key = self.inner.new_import_key(module, name);
433 self.inner.insert(key, Definition::HostFunc(func))?;
434 Ok(self)
435 }
436
437 pub fn func_wrap<Params, Args>(
459 &mut self,
460 module: &str,
461 name: &str,
462 func: impl IntoFunc<T, Params, Args>,
463 ) -> Result<&mut Self, LinkerError> {
464 self.ensure_undefined(module, name)?;
465 let func = HostFuncTrampolineEntity::wrap(func);
466 let key = self.inner.new_import_key(module, name);
467 self.inner.insert(key, Definition::HostFunc(func))?;
468 Ok(self)
469 }
470
471 pub fn get(
480 &self,
481 context: impl AsContext<Data = T>,
482 module: &str,
483 name: &str,
484 ) -> Option<Extern> {
485 match self.get_definition(context, module, name) {
486 Some(Definition::Extern(item)) => Some(*item),
487 _ => None,
488 }
489 }
490
491 fn get_definition(
499 &self,
500 context: impl AsContext<Data = T>,
501 module: &str,
502 name: &str,
503 ) -> Option<&Definition<T>> {
504 assert!(Engine::same(
505 context.as_context().store.engine(),
506 self.engine()
507 ));
508 if let Some(shared) = &self.shared {
509 if let Some(item) = shared.get_definition(module, name) {
510 return Some(item);
511 }
512 }
513 self.inner.get_definition(module, name)
514 }
515
516 pub fn instantiate(
527 &self,
528 mut context: impl AsContextMut<Data = T>,
529 module: &Module,
530 ) -> Result<InstancePre, Error> {
531 assert!(Engine::same(self.engine(), context.as_context().engine()));
532 let externals = module
535 .imports()
536 .map(|import| self.process_import(&mut context, import))
537 .collect::<Result<Vec<Extern>, Error>>()?;
538 module.instantiate(context, externals)
539 }
540
541 fn process_import(
551 &self,
552 mut context: impl AsContextMut<Data = T>,
553 import: ImportType,
554 ) -> Result<Extern, Error> {
555 assert!(Engine::same(self.engine(), context.as_context().engine()));
556 let import_name = import.import_name();
557 let module_name = import.module();
558 let field_name = import.name();
559 let resolved = self
560 .get_definition(context.as_context(), module_name, field_name)
561 .ok_or_else(|| LinkerError::missing_definition(&import))?;
562 let invalid_type = || LinkerError::invalid_type_definition(&import, &resolved.ty(&context));
563 match import.ty() {
564 ExternType::Func(expected_type) => {
565 let found_type = resolved
566 .ty(&context)
567 .func()
568 .cloned()
569 .ok_or_else(invalid_type)?;
570 if &found_type != expected_type {
571 return Err(Error::from(LinkerError::func_type_mismatch(
572 import_name,
573 expected_type,
574 &found_type,
575 )));
576 }
577 let func = resolved
578 .as_func(&mut context)
579 .expect("already asserted that `resolved` is a function");
580 Ok(Extern::Func(func))
581 }
582 ExternType::Table(expected_type) => {
583 let table = resolved
584 .as_extern()
585 .copied()
586 .and_then(Extern::into_table)
587 .ok_or_else(invalid_type)?;
588 let found_type = table.dynamic_ty(context);
589 found_type.is_subtype_or_err(expected_type).map_err(|_| {
590 LinkerError::table_type_mismatch(import_name, expected_type, &found_type)
591 })?;
592 Ok(Extern::Table(table))
593 }
594 ExternType::Memory(expected_type) => {
595 let memory = resolved
596 .as_extern()
597 .copied()
598 .and_then(Extern::into_memory)
599 .ok_or_else(invalid_type)?;
600 let found_type = memory.dynamic_ty(context);
601 found_type.is_subtype_or_err(expected_type).map_err(|_| {
602 LinkerError::invalid_memory_subtype(import_name, expected_type, &found_type)
603 })?;
604 Ok(Extern::Memory(memory))
605 }
606 ExternType::Global(expected_type) => {
607 let global = resolved
608 .as_extern()
609 .copied()
610 .and_then(Extern::into_global)
611 .ok_or_else(invalid_type)?;
612 let found_type = global.ty(context);
613 if &found_type != expected_type {
614 return Err(Error::from(LinkerError::global_type_mismatch(
615 import_name,
616 expected_type,
617 &found_type,
618 )));
619 }
620 Ok(Extern::Global(global))
621 }
622 }
623 }
624}
625
626pub mod state {
628 pub enum Constructing {}
632
633 pub enum Ready {}
638}
639
640#[derive(Debug)]
644pub struct LinkerBuilder<State, T> {
645 inner: Arc<LinkerInner<T>>,
647 marker: PhantomData<fn() -> State>,
649}
650
651impl<T> Clone for LinkerBuilder<state::Ready, T> {
652 fn clone(&self) -> Self {
653 Self {
654 inner: self.inner.clone(),
655 marker: PhantomData,
656 }
657 }
658}
659
660impl<T> LinkerBuilder<state::Ready, T> {
661 pub fn create(&self, engine: &Engine) -> Linker<T> {
663 Linker {
664 engine: engine.clone(),
665 shared: self.inner.clone().into(),
666 inner: <LinkerInner<T>>::default(),
667 }
668 }
669}
670
671impl<T> LinkerBuilder<state::Constructing, T> {
672 pub fn finish(self) -> LinkerBuilder<state::Ready, T> {
674 LinkerBuilder {
675 inner: self.inner,
676 marker: PhantomData,
677 }
678 }
679
680 fn inner_mut(&mut self) -> &mut LinkerInner<T> {
686 Arc::get_mut(&mut self.inner).unwrap_or_else(|| {
687 unreachable!("tried to define host function in LinkerBuilder after Linker creation")
688 })
689 }
690
691 pub fn func_new(
703 &mut self,
704 module: &str,
705 name: &str,
706 ty: FuncType,
707 func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
708 ) -> Result<&mut Self, LinkerError> {
709 self.inner_mut().func_new(module, name, ty, func)?;
710 Ok(self)
711 }
712
713 pub fn func_wrap<Params, Args>(
739 &mut self,
740 module: &str,
741 name: &str,
742 func: impl IntoFunc<T, Params, Args>,
743 ) -> Result<&mut Self, LinkerError> {
744 self.inner_mut().func_wrap(module, name, func)?;
745 Ok(self)
746 }
747}
748
749#[derive(Debug)]
751pub struct LinkerInner<T> {
752 strings: StringInterner,
754 definitions: BTreeMap<ImportKey, Definition<T>>,
763}
764
765impl<T> Default for LinkerInner<T> {
766 fn default() -> Self {
767 Self {
768 strings: StringInterner::default(),
769 definitions: BTreeMap::default(),
770 }
771 }
772}
773
774impl<T> Clone for LinkerInner<T> {
775 fn clone(&self) -> Self {
776 Self {
777 strings: self.strings.clone(),
778 definitions: self.definitions.clone(),
779 }
780 }
781}
782
783impl<T> LinkerInner<T> {
784 fn new_import_key(&mut self, module: &str, name: &str) -> ImportKey {
786 ImportKey::new(
787 self.strings
788 .get_or_intern_with_hint(module, InternHint::LikelyExists),
789 self.strings
790 .get_or_intern_with_hint(name, InternHint::LikelyNew),
791 )
792 }
793
794 fn get_import_key(&self, module: &str, name: &str) -> Option<ImportKey> {
796 Some(ImportKey::new(
797 self.strings.get(module)?,
798 self.strings.get(name)?,
799 ))
800 }
801
802 fn resolve_import_key(&self, key: ImportKey) -> Option<(&str, &str)> {
804 let module_name = self.strings.resolve(key.module())?;
805 let item_name = self.strings.resolve(key.name())?;
806 Some((module_name, item_name))
807 }
808
809 fn insert(&mut self, key: ImportKey, item: Definition<T>) -> Result<(), LinkerError> {
815 match self.definitions.entry(key) {
816 Entry::Occupied(_) => {
817 let (module_name, field_name) = self
818 .resolve_import_key(key)
819 .unwrap_or_else(|| panic!("encountered missing import names for key {key:?}"));
820 let import_name = ImportName::new(module_name, field_name);
821 return Err(LinkerError::DuplicateDefinition { import_name });
822 }
823 Entry::Vacant(v) => {
824 v.insert(item);
825 }
826 }
827 Ok(())
828 }
829
830 pub fn func_new(
838 &mut self,
839 module: &str,
840 name: &str,
841 ty: FuncType,
842 func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
843 ) -> Result<&mut Self, LinkerError> {
844 let func = HostFuncTrampolineEntity::new(ty, func);
845 let key = self.new_import_key(module, name);
846 self.insert(key, Definition::HostFunc(func))?;
847 Ok(self)
848 }
849
850 pub fn func_wrap<Params, Args>(
872 &mut self,
873 module: &str,
874 name: &str,
875 func: impl IntoFunc<T, Params, Args>,
876 ) -> Result<&mut Self, LinkerError> {
877 let func = HostFuncTrampolineEntity::wrap(func);
878 let key = self.new_import_key(module, name);
879 self.insert(key, Definition::HostFunc(func))?;
880 Ok(self)
881 }
882
883 fn get_definition(&self, module: &str, name: &str) -> Option<&Definition<T>> {
891 let key = self.get_import_key(module, name)?;
892 self.definitions.get(&key)
893 }
894
895 fn has_definition(&self, module: &str, name: &str) -> bool {
897 let Some(key) = self.get_import_key(module, name) else {
898 return false;
899 };
900 self.definitions.contains_key(&key)
901 }
902}
903
904#[cfg(test)]
905mod tests {
906 use crate::core::ValType;
907
908 use super::*;
909 use crate::Store;
910
911 struct HostState {
912 a: i32,
913 b: i64,
914 }
915
916 #[test]
917 fn linker_funcs_work() {
918 let engine = Engine::default();
919 let mut linker = <Linker<HostState>>::new(&engine);
920 linker
921 .func_new(
922 "host",
923 "get_a",
924 FuncType::new([], [ValType::I32]),
925 |ctx: Caller<HostState>, _params: &[Val], results: &mut [Val]| {
926 results[0] = Val::from(ctx.data().a);
927 Ok(())
928 },
929 )
930 .unwrap();
931 linker
932 .func_new(
933 "host",
934 "set_a",
935 FuncType::new([ValType::I32], []),
936 |mut ctx: Caller<HostState>, params: &[Val], _results: &mut [Val]| {
937 ctx.data_mut().a = params[0].i32().unwrap();
938 Ok(())
939 },
940 )
941 .unwrap();
942 linker
943 .func_wrap("host", "get_b", |ctx: Caller<HostState>| ctx.data().b)
944 .unwrap();
945 linker
946 .func_wrap("host", "set_b", |mut ctx: Caller<HostState>, value: i64| {
947 ctx.data_mut().b = value
948 })
949 .unwrap();
950 let a_init = 42;
951 let b_init = 77;
952 let mut store = <Store<HostState>>::new(
953 &engine,
954 HostState {
955 a: a_init,
956 b: b_init,
957 },
958 );
959 let wat = r#"
960 (module
961 (import "host" "get_a" (func $host_get_a (result i32)))
962 (import "host" "set_a" (func $host_set_a (param i32)))
963 (import "host" "get_b" (func $host_get_b (result i64)))
964 (import "host" "set_b" (func $host_set_b (param i64)))
965
966 (func (export "wasm_get_a") (result i32)
967 (call $host_get_a)
968 )
969 (func (export "wasm_set_a") (param $param i32)
970 (call $host_set_a (local.get $param))
971 )
972
973 (func (export "wasm_get_b") (result i64)
974 (call $host_get_b)
975 )
976 (func (export "wasm_set_b") (param $param i64)
977 (call $host_set_b (local.get $param))
978 )
979 )
980 "#;
981 let wasm = wat::parse_str(wat).unwrap();
982 let module = Module::new(&engine, &wasm[..]).unwrap();
983 let instance = linker
984 .instantiate(&mut store, &module)
985 .unwrap()
986 .start(&mut store)
987 .unwrap();
988
989 let wasm_get_a = instance
990 .get_typed_func::<(), i32>(&store, "wasm_get_a")
991 .unwrap();
992 let wasm_set_a = instance
993 .get_typed_func::<i32, ()>(&store, "wasm_set_a")
994 .unwrap();
995 let wasm_get_b = instance
996 .get_typed_func::<(), i64>(&store, "wasm_get_b")
997 .unwrap();
998 let wasm_set_b = instance
999 .get_typed_func::<i64, ()>(&store, "wasm_set_b")
1000 .unwrap();
1001
1002 assert_eq!(wasm_get_a.call(&mut store, ()).unwrap(), a_init);
1003 wasm_set_a.call(&mut store, 100).unwrap();
1004 assert_eq!(wasm_get_a.call(&mut store, ()).unwrap(), 100);
1005
1006 assert_eq!(wasm_get_b.call(&mut store, ()).unwrap(), b_init);
1007 wasm_set_b.call(&mut store, 200).unwrap();
1008 assert_eq!(wasm_get_b.call(&mut store, ()).unwrap(), 200);
1009 }
1010
1011 #[test]
1012 fn build_linker() {
1013 let mut builder = <Linker<()>>::build();
1014 builder
1015 .func_wrap("env", "foo", || std::println!("called foo"))
1016 .unwrap();
1017 builder
1018 .func_new(
1019 "env",
1020 "bar",
1021 FuncType::new([], []),
1022 |_caller, _params, _results| {
1023 std::println!("called bar");
1024 Ok(())
1025 },
1026 )
1027 .unwrap();
1028 let builder = builder.finish();
1029 for _ in 0..3 {
1030 let engine = Engine::default();
1031 let _ = builder.create(&engine);
1032 }
1033 }
1034
1035 #[test]
1036 fn linker_builder_uses() {
1037 use crate::{Engine, Linker, Module, Store};
1038 let wasm = wat::parse_str(
1039 r#"
1040 (module
1041 (import "host" "func.0" (func $host_func.0))
1042 (import "host" "func.1" (func $host_func.1))
1043 (func (export "hello")
1044 (call $host_func.0)
1045 (call $host_func.1)
1046 )
1047 )"#,
1048 )
1049 .unwrap();
1050 let engine = Engine::default();
1051 let mut builder = <Linker<()>>::build();
1052 builder
1053 .func_wrap("host", "func.0", |_caller: Caller<()>| ())
1054 .unwrap();
1055 builder
1056 .func_wrap("host", "func.1", |_caller: Caller<()>| ())
1057 .unwrap();
1058 let linker = builder.finish().create(&engine);
1059 let mut store = Store::new(&engine, ());
1060 let module = Module::new(&engine, &wasm[..]).unwrap();
1061 linker.instantiate(&mut store, &module).unwrap();
1062 }
1063
1064 #[test]
1065 fn linker_builder_and_linker_uses() {
1066 use crate::{Engine, Linker, Module, Store};
1067 let wasm = wat::parse_str(
1068 r#"
1069 (module
1070 (import "host" "func.0" (func $host_func.0))
1071 (import "host" "func.1" (func $host_func.1))
1072 (func (export "hello")
1073 (call $host_func.0)
1074 (call $host_func.1)
1075 )
1076 )"#,
1077 )
1078 .unwrap();
1079 let engine = Engine::default();
1080 let mut builder = <Linker<()>>::build();
1081 builder
1082 .func_wrap("host", "func.0", |_caller: Caller<()>| ())
1083 .unwrap();
1084 let mut linker = builder.finish().create(&engine);
1085 linker
1086 .func_wrap("host", "func.1", |_caller: Caller<()>| ())
1087 .unwrap();
1088 let mut store = Store::new(&engine, ());
1089 let module = Module::new(&engine, &wasm[..]).unwrap();
1090 linker.instantiate(&mut store, &module).unwrap();
1091 }
1092
1093 #[test]
1094 fn linker_builder_no_overwrite() {
1095 use crate::{Engine, Linker};
1096 let engine = Engine::default();
1097 let mut builder = <Linker<()>>::build();
1098 builder
1099 .func_wrap("host", "func.0", |_caller: Caller<()>| ())
1100 .unwrap();
1101 let mut linker = builder.finish().create(&engine);
1102 linker
1103 .func_wrap("host", "func.1", |_caller: Caller<()>| ())
1104 .unwrap();
1105 linker
1107 .func_wrap("host", "func.0", |_caller: Caller<()>| ())
1108 .unwrap_err();
1109 }
1110
1111 #[test]
1112 fn populate_via_imports() {
1113 use crate::{Engine, Func, Linker, Memory, MemoryType, Module, Store};
1114 let wasm = wat::parse_str(
1115 r#"
1116 (module
1117 (import "host" "hello" (func $host_hello (param i32) (result i32)))
1118 (import "env" "memory" (memory $mem 0 4096))
1119 (func (export "hello") (result i32)
1120 (call $host_hello (i32.const 3))
1121 (i32.const 2)
1122 i32.add
1123 )
1124 )"#,
1125 )
1126 .unwrap();
1127 let engine = Engine::default();
1128 let mut linker = <Linker<()>>::new(&engine);
1129 let mut store = Store::new(&engine, ());
1130 let memory = Memory::new(&mut store, MemoryType::new(1, Some(4096)).unwrap()).unwrap();
1131 let module = Module::new(&engine, &wasm[..]).unwrap();
1132 linker.define("env", "memory", memory).unwrap();
1133 let func = Func::new(
1134 &mut store,
1135 FuncType::new([ValType::I32], [ValType::I32]),
1136 |_caller, _params, _results| todo!(),
1137 );
1138 linker.define("host", "hello", func).unwrap();
1139 linker.instantiate(&mut store, &module).unwrap();
1140 }
1141}