Skip to main content

wasm_link/
remap.rs

1//! Export name remapping for plugin implementations.
2//!
3//! Remaps are per-plugin lookup tables. They let a plugin satisfy a canonical
4//! [`Binding`](crate::Binding) even when the plugin exports matching interfaces or
5//! functions under different names.
6
7use std::collections::HashMap;
8
9/// Maps requested item names to the item names exported by a plugin.
10///
11/// The table direction is always:
12///
13/// ```text
14/// requested item name -> exported item name
15/// ```
16pub type ItemResolutionTable = HashMap<String, String>;
17
18/// Describes where a requested interface is found in a plugin's exports.
19///
20/// `Plugin::remap_interfaces` stores these values in a map whose key is the
21/// requested interface name from the [`Binding`](crate::Binding). The [`Remap`]
22/// value then describes the interface name and item names actually exported by
23/// that plugin.
24///
25/// # Examples
26///
27/// ```
28/// use std::collections::HashMap;
29/// use wasm_link::Remap;
30///
31/// let interface_only = Remap::found_as( "legacy-root" );
32/// let one_item = Remap::resolves_item( "get-value", "legacy-get-value" );
33/// let many_items = Remap::item_resolution_table( HashMap::from([
34/// 	( "get-value".to_string(), "legacy-get-value".to_string() ),
35/// ]));
36/// let interface_and_items = Remap::found_as_with_item_resolution_table(
37/// 	"legacy-root",
38/// 	HashMap::from([( "get-value".to_string(), "legacy-get-value".to_string() )]),
39/// );
40/// # let _ = ( interface_only, one_item, many_items, interface_and_items );
41/// ```
42#[derive(Debug, Clone, Default, PartialEq, Eq)]
43pub struct Remap {
44    interface: Option<String>,
45    item_resolution_table: ItemResolutionTable,
46}
47
48impl Remap {
49    /// Creates a remap where the requested interface is found under another exported name.
50    pub fn found_as(interface: impl Into<String>) -> Self {
51        Self {
52            interface: Some(interface.into()),
53            item_resolution_table: HashMap::new(),
54        }
55    }
56
57    /// Creates a remap where one requested item resolves to another exported item name.
58    ///
59    /// The first argument is the requested item name. The second argument is the
60    /// item name exported by the plugin.
61    pub fn resolves_item(
62        requested_item: impl Into<String>,
63        exported_item: impl Into<String>,
64    ) -> Self {
65        Self {
66            interface: None,
67            item_resolution_table: HashMap::from([(requested_item.into(), exported_item.into())]),
68        }
69    }
70
71    /// Creates a remap from an item resolution table.
72    ///
73    /// The table direction is `requested item name -> exported item name`.
74    pub fn item_resolution_table(item_resolution_table: ItemResolutionTable) -> Self {
75        Self {
76            interface: None,
77            item_resolution_table,
78        }
79    }
80
81    /// Creates a remap for both the interface name and its item names.
82    ///
83    /// The item table direction is `requested item name -> exported item name`.
84    pub fn found_as_with_item_resolution_table(
85        interface: impl Into<String>,
86        item_resolution_table: ItemResolutionTable,
87    ) -> Self {
88        Self {
89            interface: Some(interface.into()),
90            item_resolution_table,
91        }
92    }
93
94    pub(crate) fn interface_name<'a>( &'a self, requested_interface: &'a str ) -> &'a str {
95        self.interface.as_deref().unwrap_or( requested_interface )
96    }
97
98    pub(crate) fn item_name<'a>( &'a self, requested_item: &'a str ) -> &'a str {
99        self.item_resolution_table
100            .get( requested_item )
101            .map_or( requested_item, String::as_str )
102    }
103}