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}