wasm_encoder/core/
imports.rs

1use crate::{
2    CORE_FUNCTION_EXACT_SORT, CORE_FUNCTION_SORT, CORE_GLOBAL_SORT, CORE_MEMORY_SORT,
3    CORE_TABLE_SORT, CORE_TAG_SORT, Encode, GlobalType, MemoryType, Section, SectionId, TableType,
4    TagType, encode_section,
5};
6use alloc::borrow::Cow;
7use alloc::vec::Vec;
8
9/// The type of an entity.
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum EntityType {
12    /// A function type.
13    ///
14    /// The value is an index into the types section.
15    Function(u32),
16    /// A table type.
17    Table(TableType),
18    /// A memory type.
19    Memory(MemoryType),
20    /// A global type.
21    Global(GlobalType),
22    /// A tag type.
23    ///
24    /// This variant is used with the exception handling proposal.
25    Tag(TagType),
26    /// A function exact type.
27    ///
28    /// The value is an index into the types section.
29    FunctionExact(u32),
30}
31
32impl Encode for EntityType {
33    fn encode(&self, sink: &mut Vec<u8>) {
34        match self {
35            Self::Function(f) => {
36                sink.push(CORE_FUNCTION_SORT);
37                f.encode(sink);
38            }
39            Self::FunctionExact(f) => {
40                sink.push(CORE_FUNCTION_EXACT_SORT);
41                f.encode(sink);
42            }
43            Self::Table(t) => {
44                sink.push(CORE_TABLE_SORT);
45                t.encode(sink);
46            }
47            Self::Memory(t) => {
48                sink.push(CORE_MEMORY_SORT);
49                t.encode(sink);
50            }
51            Self::Global(t) => {
52                sink.push(CORE_GLOBAL_SORT);
53                t.encode(sink);
54            }
55            Self::Tag(t) => {
56                sink.push(CORE_TAG_SORT);
57                t.encode(sink);
58            }
59        }
60    }
61}
62
63impl From<TableType> for EntityType {
64    fn from(t: TableType) -> Self {
65        Self::Table(t)
66    }
67}
68
69impl From<MemoryType> for EntityType {
70    fn from(t: MemoryType) -> Self {
71        Self::Memory(t)
72    }
73}
74
75impl From<GlobalType> for EntityType {
76    fn from(t: GlobalType) -> Self {
77        Self::Global(t)
78    }
79}
80
81impl From<TagType> for EntityType {
82    fn from(t: TagType) -> Self {
83        Self::Tag(t)
84    }
85}
86
87/// An import item to be used with [`Imports::Single`].
88#[derive(Clone, Debug)]
89pub struct Import<'a> {
90    /// The import's module name.
91    pub module: &'a str,
92    /// The import's item name.
93    pub name: &'a str,
94    /// The import's time.
95    pub ty: EntityType,
96}
97
98/// An import item to be used with [`Imports::Compact1`].
99#[derive(Clone, Debug)]
100pub struct ImportCompact<'a> {
101    /// The import's item name.
102    pub name: &'a str,
103    /// The import's type.
104    pub ty: EntityType,
105}
106
107/// A single entry in the import section of a WebAssembly module, possibly containing multiple imports.
108#[derive(Clone, Debug)]
109pub enum Imports<'a> {
110    /// A single import item.
111    Single(Import<'a>),
112    /// A group of imports with a common module name.
113    Compact1 {
114        /// The common module name.
115        module: &'a str,
116        /// The individual import items (name/type).
117        items: Cow<'a, [ImportCompact<'a>]>,
118    },
119    /// A group of imports with a common module name and type.
120    Compact2 {
121        /// The common module name.
122        module: &'a str,
123        /// The common import type.
124        ty: EntityType,
125        /// The individual import item names.
126        names: Cow<'a, [&'a str]>,
127    },
128}
129
130/// An encoder for the import section of WebAssembly modules.
131///
132/// # Example
133///
134/// ```rust
135/// use wasm_encoder::{MemoryType, Module, ImportSection};
136///
137/// let mut imports = ImportSection::new();
138/// imports.import(
139///     "env",
140///     "memory",
141///     MemoryType {
142///         minimum: 1,
143///         maximum: None,
144///         memory64: false,
145///         shared: false,
146///         page_size_log2: None,
147///     }
148/// );
149///
150/// let mut module = Module::new();
151/// module.section(&imports);
152///
153/// let bytes = module.finish();
154/// ```
155#[derive(Clone, Debug, Default)]
156pub struct ImportSection {
157    bytes: Vec<u8>,
158    num_added: u32,
159}
160
161impl ImportSection {
162    /// Create a new import section encoder.
163    pub fn new() -> Self {
164        Self::default()
165    }
166
167    /// The number of imports in the section.
168    pub fn len(&self) -> u32 {
169        self.num_added
170    }
171
172    /// Determines if the section is empty.
173    pub fn is_empty(&self) -> bool {
174        self.num_added == 0
175    }
176
177    /// Define imports in the import section.
178    pub fn imports<'a>(&mut self, imports: Imports<'a>) -> &mut Self {
179        match imports {
180            Imports::Single(import) => {
181                import.module.encode(&mut self.bytes);
182                import.name.encode(&mut self.bytes);
183                import.ty.encode(&mut self.bytes);
184            }
185            Imports::Compact1 { module, items } => {
186                module.encode(&mut self.bytes);
187                self.bytes.push(0x00); // empty name
188                self.bytes.push(0x7F);
189                items.len().encode(&mut self.bytes);
190                for item in items.iter() {
191                    item.name.encode(&mut self.bytes);
192                    item.ty.encode(&mut self.bytes);
193                }
194            }
195            Imports::Compact2 { module, ty, names } => {
196                module.encode(&mut self.bytes);
197                self.bytes.push(0x00); // empty name
198                self.bytes.push(0x7E);
199                ty.encode(&mut self.bytes);
200                names.len().encode(&mut self.bytes);
201                for item in names.iter() {
202                    item.encode(&mut self.bytes);
203                }
204            }
205        }
206        self.num_added += 1;
207        self
208    }
209
210    /// Define an import in the import section.
211    pub fn import(&mut self, module: &str, name: &str, ty: impl Into<EntityType>) -> &mut Self {
212        self.imports(Imports::Single(Import {
213            module,
214            name,
215            ty: ty.into(),
216        }))
217    }
218}
219
220impl Encode for ImportSection {
221    fn encode(&self, sink: &mut Vec<u8>) {
222        encode_section(sink, self.num_added, &self.bytes);
223    }
224}
225
226impl Section for ImportSection {
227    fn id(&self) -> u8 {
228        SectionId::Import.into()
229    }
230}