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_dedup = ctx
311 .as_context()
312 .engine()
313 .alloc_func_type(host_func.func_type().clone());
314 let entity = HostFuncEntity::new(ty_dedup, trampoline);
315 let func = ctx
316 .as_context_mut()
317 .store
318 .inner
319 .alloc_func(FuncEntity::Host(entity));
320 Some(func)
321 }
322 _ => None,
323 }
324 }
325}
326
327#[derive(Debug)]
329pub struct Linker<T> {
330 engine: Engine,
337 shared: Option<Arc<LinkerInner<T>>>,
341 inner: LinkerInner<T>,
343}
344
345impl<T> Clone for Linker<T> {
346 fn clone(&self) -> Linker<T> {
347 Self {
348 engine: self.engine.clone(),
349 shared: self.shared.clone(),
350 inner: self.inner.clone(),
351 }
352 }
353}
354
355impl<T> Default for Linker<T> {
356 fn default() -> Self {
357 Self::new(&Engine::default())
358 }
359}
360
361impl<T> Linker<T> {
362 pub fn new(engine: &Engine) -> Self {
364 Self {
365 engine: engine.clone(),
366 shared: None,
367 inner: LinkerInner::default(),
368 }
369 }
370
371 pub fn build() -> LinkerBuilder<state::Constructing, T> {
373 LinkerBuilder {
374 inner: Arc::new(LinkerInner::default()),
375 marker: PhantomData,
376 }
377 }
378
379 pub fn engine(&self) -> &Engine {
381 &self.engine
382 }
383
384 fn ensure_undefined(&self, module: &str, name: &str) -> Result<(), LinkerError> {
392 if let Some(shared) = &self.shared {
393 if shared.has_definition(module, name) {
394 return Err(LinkerError::DuplicateDefinition {
395 import_name: ImportName::new(module, name),
396 });
397 }
398 }
399 Ok(())
400 }
401
402 pub fn define(
408 &mut self,
409 module: &str,
410 name: &str,
411 item: impl Into<Extern>,
412 ) -> Result<&mut Self, LinkerError> {
413 self.ensure_undefined(module, name)?;
414 let key = self.inner.new_import_key(module, name);
415 self.inner.insert(key, Definition::Extern(item.into()))?;
416 Ok(self)
417 }
418
419 pub fn func_new(
427 &mut self,
428 module: &str,
429 name: &str,
430 ty: FuncType,
431 func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
432 ) -> Result<&mut Self, LinkerError> {
433 self.ensure_undefined(module, name)?;
434 let func = HostFuncTrampolineEntity::new(ty, func);
435 let key = self.inner.new_import_key(module, name);
436 self.inner.insert(key, Definition::HostFunc(func))?;
437 Ok(self)
438 }
439
440 pub fn func_wrap<Params, Args>(
462 &mut self,
463 module: &str,
464 name: &str,
465 func: impl IntoFunc<T, Params, Args>,
466 ) -> Result<&mut Self, LinkerError> {
467 self.ensure_undefined(module, name)?;
468 let func = HostFuncTrampolineEntity::wrap(func);
469 let key = self.inner.new_import_key(module, name);
470 self.inner.insert(key, Definition::HostFunc(func))?;
471 Ok(self)
472 }
473
474 pub fn get(
483 &self,
484 context: impl AsContext<Data = T>,
485 module: &str,
486 name: &str,
487 ) -> Option<Extern> {
488 match self.get_definition(context, module, name) {
489 Some(Definition::Extern(item)) => Some(*item),
490 _ => None,
491 }
492 }
493
494 fn get_definition(
502 &self,
503 context: impl AsContext<Data = T>,
504 module: &str,
505 name: &str,
506 ) -> Option<&Definition<T>> {
507 assert!(Engine::same(
508 context.as_context().store.engine(),
509 self.engine()
510 ));
511 if let Some(shared) = &self.shared {
512 if let Some(item) = shared.get_definition(module, name) {
513 return Some(item);
514 }
515 }
516 self.inner.get_definition(module, name)
517 }
518
519 pub fn instantiate(
530 &self,
531 mut context: impl AsContextMut<Data = T>,
532 module: &Module,
533 ) -> Result<InstancePre, Error> {
534 assert!(Engine::same(self.engine(), context.as_context().engine()));
535 let externals = module
538 .imports()
539 .map(|import| self.process_import(&mut context, import))
540 .collect::<Result<Vec<Extern>, Error>>()?;
541 module.instantiate(context, externals)
542 }
543
544 fn process_import(
554 &self,
555 mut context: impl AsContextMut<Data = T>,
556 import: ImportType,
557 ) -> Result<Extern, Error> {
558 assert!(Engine::same(self.engine(), context.as_context().engine()));
559 let import_name = import.import_name();
560 let module_name = import.module();
561 let field_name = import.name();
562 let resolved = self
563 .get_definition(context.as_context(), module_name, field_name)
564 .ok_or_else(|| LinkerError::missing_definition(&import))?;
565 let invalid_type = || LinkerError::invalid_type_definition(&import, &resolved.ty(&context));
566 match import.ty() {
567 ExternType::Func(expected_type) => {
568 let found_type = resolved
569 .ty(&context)
570 .func()
571 .cloned()
572 .ok_or_else(invalid_type)?;
573 if &found_type != expected_type {
574 return Err(Error::from(LinkerError::func_type_mismatch(
575 import_name,
576 expected_type,
577 &found_type,
578 )));
579 }
580 let func = resolved
581 .as_func(&mut context)
582 .expect("already asserted that `resolved` is a function");
583 Ok(Extern::Func(func))
584 }
585 ExternType::Table(expected_type) => {
586 let table = resolved
587 .as_extern()
588 .copied()
589 .and_then(Extern::into_table)
590 .ok_or_else(invalid_type)?;
591 let found_type = table.dynamic_ty(context);
592 found_type.is_subtype_or_err(expected_type).map_err(|_| {
593 LinkerError::table_type_mismatch(import_name, expected_type, &found_type)
594 })?;
595 Ok(Extern::Table(table))
596 }
597 ExternType::Memory(expected_type) => {
598 let memory = resolved
599 .as_extern()
600 .copied()
601 .and_then(Extern::into_memory)
602 .ok_or_else(invalid_type)?;
603 let found_type = memory.dynamic_ty(context);
604 found_type.is_subtype_or_err(expected_type).map_err(|_| {
605 LinkerError::invalid_memory_subtype(import_name, expected_type, &found_type)
606 })?;
607 Ok(Extern::Memory(memory))
608 }
609 ExternType::Global(expected_type) => {
610 let global = resolved
611 .as_extern()
612 .copied()
613 .and_then(Extern::into_global)
614 .ok_or_else(invalid_type)?;
615 let found_type = global.ty(context);
616 if &found_type != expected_type {
617 return Err(Error::from(LinkerError::global_type_mismatch(
618 import_name,
619 expected_type,
620 &found_type,
621 )));
622 }
623 Ok(Extern::Global(global))
624 }
625 }
626 }
627}
628
629pub mod state {
631 pub enum Constructing {}
635
636 pub enum Ready {}
641}
642
643#[derive(Debug)]
647pub struct LinkerBuilder<State, T> {
648 inner: Arc<LinkerInner<T>>,
650 marker: PhantomData<fn() -> State>,
652}
653
654impl<T> Clone for LinkerBuilder<state::Ready, T> {
655 fn clone(&self) -> Self {
656 Self {
657 inner: self.inner.clone(),
658 marker: PhantomData,
659 }
660 }
661}
662
663impl<T> LinkerBuilder<state::Ready, T> {
664 pub fn create(&self, engine: &Engine) -> Linker<T> {
666 Linker {
667 engine: engine.clone(),
668 shared: self.inner.clone().into(),
669 inner: <LinkerInner<T>>::default(),
670 }
671 }
672}
673
674impl<T> LinkerBuilder<state::Constructing, T> {
675 pub fn finish(self) -> LinkerBuilder<state::Ready, T> {
677 LinkerBuilder {
678 inner: self.inner,
679 marker: PhantomData,
680 }
681 }
682
683 fn inner_mut(&mut self) -> &mut LinkerInner<T> {
689 Arc::get_mut(&mut self.inner).unwrap_or_else(|| {
690 unreachable!("tried to define host function in LinkerBuilder after Linker creation")
691 })
692 }
693
694 pub fn func_new(
706 &mut self,
707 module: &str,
708 name: &str,
709 ty: FuncType,
710 func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
711 ) -> Result<&mut Self, LinkerError> {
712 self.inner_mut().func_new(module, name, ty, func)?;
713 Ok(self)
714 }
715
716 pub fn func_wrap<Params, Args>(
742 &mut self,
743 module: &str,
744 name: &str,
745 func: impl IntoFunc<T, Params, Args>,
746 ) -> Result<&mut Self, LinkerError> {
747 self.inner_mut().func_wrap(module, name, func)?;
748 Ok(self)
749 }
750}
751
752#[derive(Debug)]
754pub struct LinkerInner<T> {
755 strings: StringInterner,
757 definitions: BTreeMap<ImportKey, Definition<T>>,
766}
767
768impl<T> Default for LinkerInner<T> {
769 fn default() -> Self {
770 Self {
771 strings: StringInterner::default(),
772 definitions: BTreeMap::default(),
773 }
774 }
775}
776
777impl<T> Clone for LinkerInner<T> {
778 fn clone(&self) -> Self {
779 Self {
780 strings: self.strings.clone(),
781 definitions: self.definitions.clone(),
782 }
783 }
784}
785
786impl<T> LinkerInner<T> {
787 fn new_import_key(&mut self, module: &str, name: &str) -> ImportKey {
789 ImportKey::new(
790 self.strings
791 .get_or_intern_with_hint(module, InternHint::LikelyExists),
792 self.strings
793 .get_or_intern_with_hint(name, InternHint::LikelyNew),
794 )
795 }
796
797 fn get_import_key(&self, module: &str, name: &str) -> Option<ImportKey> {
799 Some(ImportKey::new(
800 self.strings.get(module)?,
801 self.strings.get(name)?,
802 ))
803 }
804
805 fn resolve_import_key(&self, key: ImportKey) -> Option<(&str, &str)> {
807 let module_name = self.strings.resolve(key.module())?;
808 let item_name = self.strings.resolve(key.name())?;
809 Some((module_name, item_name))
810 }
811
812 fn insert(&mut self, key: ImportKey, item: Definition<T>) -> Result<(), LinkerError> {
818 match self.definitions.entry(key) {
819 Entry::Occupied(_) => {
820 let (module_name, field_name) = self
821 .resolve_import_key(key)
822 .unwrap_or_else(|| panic!("encountered missing import names for key {key:?}"));
823 let import_name = ImportName::new(module_name, field_name);
824 return Err(LinkerError::DuplicateDefinition { import_name });
825 }
826 Entry::Vacant(v) => {
827 v.insert(item);
828 }
829 }
830 Ok(())
831 }
832
833 pub fn func_new(
841 &mut self,
842 module: &str,
843 name: &str,
844 ty: FuncType,
845 func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
846 ) -> Result<&mut Self, LinkerError> {
847 let func = HostFuncTrampolineEntity::new(ty, func);
848 let key = self.new_import_key(module, name);
849 self.insert(key, Definition::HostFunc(func))?;
850 Ok(self)
851 }
852
853 pub fn func_wrap<Params, Args>(
875 &mut self,
876 module: &str,
877 name: &str,
878 func: impl IntoFunc<T, Params, Args>,
879 ) -> Result<&mut Self, LinkerError> {
880 let func = HostFuncTrampolineEntity::wrap(func);
881 let key = self.new_import_key(module, name);
882 self.insert(key, Definition::HostFunc(func))?;
883 Ok(self)
884 }
885
886 fn get_definition(&self, module: &str, name: &str) -> Option<&Definition<T>> {
894 let key = self.get_import_key(module, name)?;
895 self.definitions.get(&key)
896 }
897
898 fn has_definition(&self, module: &str, name: &str) -> bool {
900 let Some(key) = self.get_import_key(module, name) else {
901 return false;
902 };
903 self.definitions.contains_key(&key)
904 }
905}
906
907#[cfg(test)]
908mod tests {
909 use crate::core::ValType;
910
911 use super::*;
912 use crate::Store;
913
914 struct HostState {
915 a: i32,
916 b: i64,
917 }
918
919 #[test]
920 fn linker_funcs_work() {
921 let engine = Engine::default();
922 let mut linker = <Linker<HostState>>::new(&engine);
923 linker
924 .func_new(
925 "host",
926 "get_a",
927 FuncType::new([], [ValType::I32]),
928 |ctx: Caller<HostState>, _params: &[Val], results: &mut [Val]| {
929 results[0] = Val::from(ctx.data().a);
930 Ok(())
931 },
932 )
933 .unwrap();
934 linker
935 .func_new(
936 "host",
937 "set_a",
938 FuncType::new([ValType::I32], []),
939 |mut ctx: Caller<HostState>, params: &[Val], _results: &mut [Val]| {
940 ctx.data_mut().a = params[0].i32().unwrap();
941 Ok(())
942 },
943 )
944 .unwrap();
945 linker
946 .func_wrap("host", "get_b", |ctx: Caller<HostState>| ctx.data().b)
947 .unwrap();
948 linker
949 .func_wrap("host", "set_b", |mut ctx: Caller<HostState>, value: i64| {
950 ctx.data_mut().b = value
951 })
952 .unwrap();
953 let a_init = 42;
954 let b_init = 77;
955 let mut store = <Store<HostState>>::new(
956 &engine,
957 HostState {
958 a: a_init,
959 b: b_init,
960 },
961 );
962 let wat = r#"
963 (module
964 (import "host" "get_a" (func $host_get_a (result i32)))
965 (import "host" "set_a" (func $host_set_a (param i32)))
966 (import "host" "get_b" (func $host_get_b (result i64)))
967 (import "host" "set_b" (func $host_set_b (param i64)))
968
969 (func (export "wasm_get_a") (result i32)
970 (call $host_get_a)
971 )
972 (func (export "wasm_set_a") (param $param i32)
973 (call $host_set_a (local.get $param))
974 )
975
976 (func (export "wasm_get_b") (result i64)
977 (call $host_get_b)
978 )
979 (func (export "wasm_set_b") (param $param i64)
980 (call $host_set_b (local.get $param))
981 )
982 )
983 "#;
984 let wasm = wat::parse_str(wat).unwrap();
985 let module = Module::new(&engine, &wasm[..]).unwrap();
986 let instance = linker
987 .instantiate(&mut store, &module)
988 .unwrap()
989 .start(&mut store)
990 .unwrap();
991
992 let wasm_get_a = instance
993 .get_typed_func::<(), i32>(&store, "wasm_get_a")
994 .unwrap();
995 let wasm_set_a = instance
996 .get_typed_func::<i32, ()>(&store, "wasm_set_a")
997 .unwrap();
998 let wasm_get_b = instance
999 .get_typed_func::<(), i64>(&store, "wasm_get_b")
1000 .unwrap();
1001 let wasm_set_b = instance
1002 .get_typed_func::<i64, ()>(&store, "wasm_set_b")
1003 .unwrap();
1004
1005 assert_eq!(wasm_get_a.call(&mut store, ()).unwrap(), a_init);
1006 wasm_set_a.call(&mut store, 100).unwrap();
1007 assert_eq!(wasm_get_a.call(&mut store, ()).unwrap(), 100);
1008
1009 assert_eq!(wasm_get_b.call(&mut store, ()).unwrap(), b_init);
1010 wasm_set_b.call(&mut store, 200).unwrap();
1011 assert_eq!(wasm_get_b.call(&mut store, ()).unwrap(), 200);
1012 }
1013
1014 #[test]
1015 fn build_linker() {
1016 let mut builder = <Linker<()>>::build();
1017 builder
1018 .func_wrap("env", "foo", || std::println!("called foo"))
1019 .unwrap();
1020 builder
1021 .func_new(
1022 "env",
1023 "bar",
1024 FuncType::new([], []),
1025 |_caller, _params, _results| {
1026 std::println!("called bar");
1027 Ok(())
1028 },
1029 )
1030 .unwrap();
1031 let builder = builder.finish();
1032 for _ in 0..3 {
1033 let engine = Engine::default();
1034 let _ = builder.create(&engine);
1035 }
1036 }
1037
1038 #[test]
1039 fn linker_builder_uses() {
1040 use crate::{Engine, Linker, Module, Store};
1041 let wasm = wat::parse_str(
1042 r#"
1043 (module
1044 (import "host" "func.0" (func $host_func.0))
1045 (import "host" "func.1" (func $host_func.1))
1046 (func (export "hello")
1047 (call $host_func.0)
1048 (call $host_func.1)
1049 )
1050 )"#,
1051 )
1052 .unwrap();
1053 let engine = Engine::default();
1054 let mut builder = <Linker<()>>::build();
1055 builder
1056 .func_wrap("host", "func.0", |_caller: Caller<()>| unimplemented!())
1057 .unwrap();
1058 builder
1059 .func_wrap("host", "func.1", |_caller: Caller<()>| unimplemented!())
1060 .unwrap();
1061 let linker = builder.finish().create(&engine);
1062 let mut store = Store::new(&engine, ());
1063 let module = Module::new(&engine, &wasm[..]).unwrap();
1064 linker.instantiate(&mut store, &module).unwrap();
1065 }
1066
1067 #[test]
1068 fn linker_builder_and_linker_uses() {
1069 use crate::{Engine, Linker, Module, Store};
1070 let wasm = wat::parse_str(
1071 r#"
1072 (module
1073 (import "host" "func.0" (func $host_func.0))
1074 (import "host" "func.1" (func $host_func.1))
1075 (func (export "hello")
1076 (call $host_func.0)
1077 (call $host_func.1)
1078 )
1079 )"#,
1080 )
1081 .unwrap();
1082 let engine = Engine::default();
1083 let mut builder = <Linker<()>>::build();
1084 builder
1085 .func_wrap("host", "func.0", |_caller: Caller<()>| unimplemented!())
1086 .unwrap();
1087 let mut linker = builder.finish().create(&engine);
1088 linker
1089 .func_wrap("host", "func.1", |_caller: Caller<()>| unimplemented!())
1090 .unwrap();
1091 let mut store = Store::new(&engine, ());
1092 let module = Module::new(&engine, &wasm[..]).unwrap();
1093 linker.instantiate(&mut store, &module).unwrap();
1094 }
1095
1096 #[test]
1097 fn linker_builder_no_overwrite() {
1098 use crate::{Engine, Linker};
1099 let engine = Engine::default();
1100 let mut builder = <Linker<()>>::build();
1101 builder
1102 .func_wrap("host", "func.0", |_caller: Caller<()>| unimplemented!())
1103 .unwrap();
1104 let mut linker = builder.finish().create(&engine);
1105 linker
1106 .func_wrap("host", "func.1", |_caller: Caller<()>| unimplemented!())
1107 .unwrap();
1108 linker
1110 .func_wrap("host", "func.0", |_caller: Caller<()>| unimplemented!())
1111 .unwrap_err();
1112 }
1113
1114 #[test]
1115 fn populate_via_imports() {
1116 use crate::{Engine, Func, Linker, Memory, MemoryType, Module, Store};
1117 let wasm = wat::parse_str(
1118 r#"
1119 (module
1120 (import "host" "hello" (func $host_hello (param i32) (result i32)))
1121 (import "env" "memory" (memory $mem 0 4096))
1122 (func (export "hello") (result i32)
1123 (call $host_hello (i32.const 3))
1124 (i32.const 2)
1125 i32.add
1126 )
1127 )"#,
1128 )
1129 .unwrap();
1130 let engine = Engine::default();
1131 let mut linker = <Linker<()>>::new(&engine);
1132 let mut store = Store::new(&engine, ());
1133 let memory = Memory::new(&mut store, MemoryType::new(1, Some(4096)).unwrap()).unwrap();
1134 let module = Module::new(&engine, &wasm[..]).unwrap();
1135 linker.define("env", "memory", memory).unwrap();
1136 let func = Func::new(
1137 &mut store,
1138 FuncType::new([ValType::I32], [ValType::I32]),
1139 |_caller, _params, _results| todo!(),
1140 );
1141 linker.define("host", "hello", func).unwrap();
1142 linker.instantiate(&mut store, &module).unwrap();
1143 }
1144}