1 | use crate::{ |
2 | encode_section, Encode, GlobalType, MemoryType, Section, SectionId, TableType, TagType, |
3 | CORE_FUNCTION_SORT, CORE_GLOBAL_SORT, CORE_MEMORY_SORT, CORE_TABLE_SORT, CORE_TAG_SORT, |
4 | }; |
5 | use alloc::vec::Vec; |
6 | |
7 | /// The type of an entity. |
8 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
9 | pub enum EntityType { |
10 | /// A function type. |
11 | /// |
12 | /// The value is an index into the types section. |
13 | Function(u32), |
14 | /// A table type. |
15 | Table(TableType), |
16 | /// A memory type. |
17 | Memory(MemoryType), |
18 | /// A global type. |
19 | Global(GlobalType), |
20 | /// A tag type. |
21 | /// |
22 | /// This variant is used with the exception handling proposal. |
23 | Tag(TagType), |
24 | } |
25 | |
26 | impl Encode for EntityType { |
27 | fn encode(&self, sink: &mut Vec<u8>) { |
28 | match self { |
29 | Self::Function(i) => { |
30 | sink.push(CORE_FUNCTION_SORT); |
31 | i.encode(sink); |
32 | } |
33 | Self::Table(t) => { |
34 | sink.push(CORE_TABLE_SORT); |
35 | t.encode(sink); |
36 | } |
37 | Self::Memory(t) => { |
38 | sink.push(CORE_MEMORY_SORT); |
39 | t.encode(sink); |
40 | } |
41 | Self::Global(t) => { |
42 | sink.push(CORE_GLOBAL_SORT); |
43 | t.encode(sink); |
44 | } |
45 | Self::Tag(t) => { |
46 | sink.push(CORE_TAG_SORT); |
47 | t.encode(sink); |
48 | } |
49 | } |
50 | } |
51 | } |
52 | |
53 | impl From<TableType> for EntityType { |
54 | fn from(t: TableType) -> Self { |
55 | Self::Table(t) |
56 | } |
57 | } |
58 | |
59 | impl From<MemoryType> for EntityType { |
60 | fn from(t: MemoryType) -> Self { |
61 | Self::Memory(t) |
62 | } |
63 | } |
64 | |
65 | impl From<GlobalType> for EntityType { |
66 | fn from(t: GlobalType) -> Self { |
67 | Self::Global(t) |
68 | } |
69 | } |
70 | |
71 | impl From<TagType> for EntityType { |
72 | fn from(t: TagType) -> Self { |
73 | Self::Tag(t) |
74 | } |
75 | } |
76 | |
77 | /// An encoder for the import section of WebAssembly modules. |
78 | /// |
79 | /// # Example |
80 | /// |
81 | /// ```rust |
82 | /// use wasm_encoder::{MemoryType, Module, ImportSection}; |
83 | /// |
84 | /// let mut imports = ImportSection::new(); |
85 | /// imports.import( |
86 | /// "env" , |
87 | /// "memory" , |
88 | /// MemoryType { |
89 | /// minimum: 1, |
90 | /// maximum: None, |
91 | /// memory64: false, |
92 | /// shared: false, |
93 | /// page_size_log2: None, |
94 | /// } |
95 | /// ); |
96 | /// |
97 | /// let mut module = Module::new(); |
98 | /// module.section(&imports); |
99 | /// |
100 | /// let bytes = module.finish(); |
101 | /// ``` |
102 | #[derive (Clone, Debug, Default)] |
103 | pub struct ImportSection { |
104 | bytes: Vec<u8>, |
105 | num_added: u32, |
106 | } |
107 | |
108 | impl ImportSection { |
109 | /// Create a new import section encoder. |
110 | pub fn new() -> Self { |
111 | Self::default() |
112 | } |
113 | |
114 | /// The number of imports in the section. |
115 | pub fn len(&self) -> u32 { |
116 | self.num_added |
117 | } |
118 | |
119 | /// Determines if the section is empty. |
120 | pub fn is_empty(&self) -> bool { |
121 | self.num_added == 0 |
122 | } |
123 | |
124 | /// Define an import in the import section. |
125 | pub fn import(&mut self, module: &str, field: &str, ty: impl Into<EntityType>) -> &mut Self { |
126 | module.encode(&mut self.bytes); |
127 | field.encode(&mut self.bytes); |
128 | ty.into().encode(&mut self.bytes); |
129 | self.num_added += 1; |
130 | self |
131 | } |
132 | } |
133 | |
134 | impl Encode for ImportSection { |
135 | fn encode(&self, sink: &mut Vec<u8>) { |
136 | encode_section(sink, self.num_added, &self.bytes); |
137 | } |
138 | } |
139 | |
140 | impl Section for ImportSection { |
141 | fn id(&self) -> u8 { |
142 | SectionId::Import.into() |
143 | } |
144 | } |
145 | |