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