11use crate :: {
22 Extern , ExternType , Func , FuncType , GlobalType , ImportType , Instance , IntoFunc , Module , Store ,
33} ;
4- use anyhow:: { bail, Result } ;
4+ use anyhow:: { anyhow , bail, Result } ;
55use std:: collections:: hash_map:: { Entry , HashMap } ;
66use std:: rc:: Rc ;
77
@@ -270,6 +270,27 @@ impl Linker {
270270 Ok ( self )
271271 }
272272
273+ /// Aliases one module's name as another.
274+ ///
275+ /// This method will alias all currently defined under `module` to also be
276+ /// defined under the name `as_module` too.
277+ ///
278+ /// # Errors
279+ ///
280+ /// Returns an error if any shadowing violations happen while defining new
281+ /// items.
282+ pub fn alias ( & mut self , module : & str , as_module : & str ) -> Result < ( ) > {
283+ let items = self
284+ . iter ( )
285+ . filter ( |( m, _, _) | * m == module)
286+ . map ( |( _, name, item) | ( name. to_string ( ) , item. clone ( ) ) )
287+ . collect :: < Vec < _ > > ( ) ;
288+ for ( name, item) in items {
289+ self . define ( as_module, & name, item) ?;
290+ }
291+ Ok ( ( ) )
292+ }
293+
273294 fn insert ( & mut self , module : & str , name : & str , ty : & ExternType , item : Extern ) -> Result < ( ) > {
274295 let key = self . import_key ( module, name, ty) ;
275296 match self . map . entry ( key) {
@@ -357,7 +378,7 @@ impl Linker {
357378 pub fn instantiate ( & self , module : & Module ) -> Result < Instance > {
358379 let mut imports = Vec :: new ( ) ;
359380 for import in module. imports ( ) {
360- if let Some ( item) = self . import_get ( import) {
381+ if let Some ( item) = self . get ( import) {
361382 imports. push ( item. clone ( ) ) ;
362383 continue ;
363384 }
@@ -395,7 +416,30 @@ impl Linker {
395416 Instance :: new ( module, & imports)
396417 }
397418
398- fn import_get ( & self , import : & ImportType ) -> Option < & Extern > {
419+ /// Returns the [`Store`] that this linker is connected to.
420+ pub fn store ( & self ) -> & Store {
421+ & self . store
422+ }
423+
424+ /// Returns an iterator over all items defined in this `Linker`.
425+ ///
426+ /// The iterator returned will yield 3-tuples where the first two elements
427+ /// are the module name and item name for the external item, and the third
428+ /// item is the item itself that is defined.
429+ ///
430+ /// Note that multiple `Extern` items may be defined for the same
431+ /// module/name pair.
432+ pub fn iter ( & self ) -> impl Iterator < Item = ( & str , & str , & Extern ) > {
433+ self . map
434+ . iter ( )
435+ . map ( move |( key, item) | ( & * self . strings [ key. module ] , & * self . strings [ key. name ] , item) )
436+ }
437+
438+ /// Looks up a value in this `Linker` which matches the `import` type
439+ /// provided.
440+ ///
441+ /// Returns `None` if no match was found.
442+ pub fn get ( & self , import : & ImportType ) -> Option < & Extern > {
399443 let key = ImportKey {
400444 module : * self . string2idx . get ( import. module ( ) ) ?,
401445 name : * self . string2idx . get ( import. name ( ) ) ?,
@@ -404,8 +448,37 @@ impl Linker {
404448 self . map . get ( & key)
405449 }
406450
407- /// Returns the [`Store`] that this linker is connected to.
408- pub fn store ( & self ) -> & Store {
409- & self . store
451+ /// Returns all items defined for the `module` and `name` pair.
452+ ///
453+ /// This may return an empty iterator, but it may also return multiple items
454+ /// if the module/name have been defined twice.
455+ pub fn get_by_name < ' a : ' p , ' p > (
456+ & ' a self ,
457+ module : & ' p str ,
458+ name : & ' p str ,
459+ ) -> impl Iterator < Item = & ' a Extern > + ' p {
460+ self . map
461+ . iter ( )
462+ . filter ( move |( key, _item) | {
463+ & * self . strings [ key. module ] == module && & * self . strings [ key. name ] == name
464+ } )
465+ . map ( |( _, item) | item)
466+ }
467+
468+ /// Returns the single item defined for the `module` and `name` pair.
469+ ///
470+ /// Unlike the similar [`Linker::get_by_name`] method this function returns
471+ /// a single `&Extern` item. If the `module` and `name` pair isn't defined
472+ /// in this linker then an error is returned. If more than one value exists
473+ /// for the `module` and `name` pairs, then an error is returned as well.
474+ pub fn get_one_by_name ( & self , module : & str , name : & str ) -> Result < & Extern > {
475+ let mut items = self . get_by_name ( module, name) ;
476+ let ret = items
477+ . next ( )
478+ . ok_or_else ( || anyhow ! ( "no item named `{}` in `{}`" , name, module) ) ?;
479+ if items. next ( ) . is_some ( ) {
480+ bail ! ( "too many items named `{}` in `{}`" , name, module) ;
481+ }
482+ Ok ( ret)
410483 }
411484}
0 commit comments