1use util::*;
2use types::*;
3use Dump;
4
5#[derive(Debug, Clone)]
6pub struct Module {
7 pub unknown: Option<String>,
9 pub types: Option<Vec<FuncType>>,
10 pub imports: Option<Vec<ImportEntry>>,
11 pub functions: Option<Vec<Function>>,
12 pub tables: Option<Vec<TableType>>,
13 pub memories: Option<Vec<MemoryType>>,
14 pub globals: Option<Vec<GlobalVariable>>,
15 pub exports: Option<Vec<ExportEntry>>,
16 pub start: Option<FunctionIndex>,
17 pub elements: Option<Vec<ElemSegment>>,
18 pub codes: Option<Vec<FunctionBody>>,
19 pub data: Option<Vec<DataSegment>>,
20}
21
22impl Module {
23 pub fn function_index_of(&self, i: ImportIndex) -> Result<FunctionSpaceIndex, ImportIndex> {
24 match self.imports {
25 None => return Err(i),
26 Some(ref imports) => {
27 if let Some(&ImportEntry {kind: ImportKind::Function(_) ,..}) =imports.get(*i as usize) {
28 let index = imports.iter()
29 .take(*i as usize)
30 .filter(|e| e.kind.is_function())
31 .count();
32 Ok(FunctionSpaceIndex(InnerFunctionSpaceIndex::Import(ImportedFunctionIndex(index as u32))))
33 } else {
34 return Err(i)
35 }
36 }
37 }
38 }
39}
40
41impl Dump for Module {
42 fn dump(&self, buf: &mut Vec<u8>) -> usize {
43 let mut size = 0;
44
45 let magic = b"\0asm";
46 size += write_slice(buf, magic);
47
48 let version = 0x01;
49 size += write_uint32(buf, version);
50
51
52 let mut v = Vec::new();
53 macro_rules! do_section {
54 ($code: expr, $field: expr) => {{
55 let field = &$field;
56 for xs in field {
57 v.clear();
58 let mut section_size = 0;
59 let sec = &mut v;
60 section_size += write_varuint32(sec, xs.len() as u32);
61 for x in xs {
62 section_size += x.dump(sec);
63 }
64
65 size += write_uint8(buf, $code);
66 size += write_varuint32(buf, section_size as u32);
67 size += write_slice(buf, &sec);
68 }
69 }};
70 }
71
72
73 do_section!(0x01, self.types);
74 do_section!(0x02, self.imports);
75 do_section!(0x03, self.functions);
76 do_section!(0x04, self.tables);
77 do_section!(0x05, self.memories);
78 do_section!(0x06, self.globals);
79 do_section!(0x07, self.exports);
80 {
81 for index in self.start {
82 v.clear();
83 let mut section_size = 0;
84 let sec = &mut v;
85 section_size += write_varuint32(sec, *index);
86
87 size += write_uint8(buf, 0x08);
88 size += write_varuint32(buf, section_size as u32);
89 size += write_slice(buf, &sec);
90 }
91 }
92 do_section!(0x09, self.elements);
93 do_section!(0x0a, self.codes);
94 do_section!(0x0b, self.data);
95 size
96 }
97}
98
99#[derive(Debug, Clone)]
100pub struct ImportEntry {
101 pub module: String,
102 pub field: String,
103 pub kind: ImportKind,
104}
105
106#[derive(Debug, Clone)]
107pub enum ImportKind {
108 Function(TypeIndex),
109 Table(TableType),
110 Memory(MemoryType),
111 Global(GlobalType),
112}
113
114impl ImportKind {
115 pub fn is_function(&self) -> bool {
116 if let &ImportKind::Function(_) = self {
117 true
118 } else {
119 false
120 }
121 }
122
123 pub fn is_table(&self) -> bool {
124 if let &ImportKind::Table(_) = self {
125 true
126 } else {
127 false
128 }
129 }
130
131 pub fn is_memory(&self) -> bool {
132 if let &ImportKind::Memory(_) = self {
133 true
134 } else {
135 false
136 }
137 }
138
139 pub fn is_global(&self) -> bool {
140 if let &ImportKind::Global(_) = self {
141 true
142 } else {
143 false
144 }
145 }
146}
147
148impl Dump for ImportEntry {
149 fn dump(&self, buf: &mut Vec<u8>) -> usize {
150 let mut size = 0;
151 let module = &self.module;
152 let field = &self.field;
153
154 size += write_varuint32(buf, module.len() as u32);
155 size += write_slice(buf, module.as_bytes());
156
157 size += write_varuint32(buf, field.len() as u32);
158 size += write_slice(buf, field.as_bytes());
159
160 size += self.kind.dump(buf);
161
162 size
163
164 }
165}
166
167impl Dump for ImportKind {
168 fn dump(&self, buf: &mut Vec<u8>) -> usize {
169 use self::ImportKind::*;
170 let mut size = 0;
171 match self {
172 &Function(ref id) => {
173 size += write_uint8(buf, 0);
174 size += write_varuint32(buf, **id);
175 size
176 }
177 &Table(ref tbl) => {
178 size += write_uint8(buf, 1);
179 size += tbl.dump(buf);
180 size
181 }
182 &Memory(ref m) => {
183 size += write_uint8(buf, 2);
184 size += m.dump(buf);
185 size
186
187 }
188 &Global(ref glb) => {
189 size += write_uint8(buf, 3);
190 size += glb.dump(buf);
191 size
192
193 }
194
195 }
196 }
197}
198
199
200#[derive(Debug, Clone)]
201pub struct Function(pub TypeIndex);
202
203impl Dump for Function {
204 fn dump(&self, buf: &mut Vec<u8>) -> usize {
205 write_varuint32(buf, *self.0)
206 }
207}
208
209#[derive(Debug, Clone)]
210pub struct GlobalVariable {
211 pub ty: GlobalType,
212 pub init: InitExpr,
213}
214
215
216impl Dump for GlobalVariable {
217 fn dump(&self, buf: &mut Vec<u8>) -> usize {
218 let mut size = 0;
219
220 size += self.ty.dump(buf);
221 size += self.init.dump(buf);
222 size
223 }
224}
225
226#[derive(Debug, Clone)]
227pub struct ExportEntry {
228 pub field: String,
229 pub kind: ExportKind,
230}
231
232#[derive(Debug, Clone)]
233pub enum ExportKind {
234 Function(FunctionIndex),
235 Table(TableIndex),
236 Memory(MemoryIndex),
237 Global(GlobalIndex),
238}
239
240impl Dump for ExportEntry {
241 fn dump(&self, buf: &mut Vec<u8>) -> usize {
242 let mut size = 0;
243 let field = &self.field;
244
245 size += write_varuint32(buf, field.len() as u32);
246 size += write_slice(buf, field.as_bytes());
247
248 size += self.kind.dump(buf);
249
250 size
251 }
252}
253
254impl Dump for ExportKind {
255 fn dump(&self, buf: &mut Vec<u8>) -> usize {
256 use self::ExportKind::*;
257 let mut size = 0;
258 match self {
259 &Function(ref i) => {
260 size += write_uint8(buf, 0);
261 size += write_varuint32(buf, **i);
262 }
263 &Table(ref i) => {
264 size += write_uint8(buf, 1);
265 size += write_varuint32(buf, **i);
266 }
267 &Memory(ref i) => {
268 size += write_uint8(buf, 2);
269 size += write_varuint32(buf, **i);
270 }
271 &Global(ref i) => {
272 size += write_uint8(buf, 3);
273 size += write_varuint32(buf, **i);
274 }
275 }
276 size
277 }
278}
279
280#[derive(Debug, Clone)]
281pub struct ElemSegment {
282 pub index: TableIndex,
283 pub offset: InitExpr,
284 pub elems: Vec<FunctionSpaceIndex>,
285}
286
287impl Dump for ElemSegment {
288 fn dump(&self, buf: &mut Vec<u8>) -> usize {
289 let mut size = 0;
290
291 let elems = &self.elems;
292 assert_eq!(*self.index, 0);
293 size += write_varuint32(buf, *self.index);
294 size += self.offset.dump(buf);
295
296 size += write_varuint32(buf, elems.len() as u32);
297 for e in elems.iter() {
298 size += write_varuint32(buf, **e);
299 }
300 size
301 }
302}
303
304#[derive(Debug, Clone)]
305pub struct FunctionBody {
306 pub locals: Vec<LocalEntry>,
307 pub code: Code,
308}
309
310impl FunctionBody {
311 pub fn resolve_functions(&mut self, nimports: u32) {
312 for op in self.code.0.iter_mut() {
313 op.resolve_functions(nimports)
314 }
315 }
316}
317
318
319impl Dump for FunctionBody {
320 fn dump(&self, buf: &mut Vec<u8>) -> usize {
321 let mut size = 0;
322
323 let locals = &self.locals;
324 let code = &self.code;
325
326 let body_size;
327 let mut body = Vec::new();
328 {
329 let mut size = 0;
330 let buf = &mut body;
331 size += write_varuint32(buf, locals.len() as u32);
332 for l in locals.iter() {
333 size += l.dump(buf);
334 }
335
336 size += code.dump(buf);
337 size += write_uint8(buf, 0x0b);
338
339 body_size = size;
340 }
341
342
343 size += write_varuint32(buf, body_size as u32);
344 size += write_slice(buf, &body);
345
346 size
347 }
348}
349
350
351#[derive(Debug, Clone)]
352pub struct LocalEntry {
353 pub count: u32,
354 pub ty: ValueType,
355}
356
357
358impl Dump for LocalEntry {
359 fn dump(&self, buf: &mut Vec<u8>) -> usize {
360 let mut size = 0;
361
362 size += write_varuint32(buf, self.count);
363 size += self.ty.dump(buf);
364
365 size
366 }
367}
368
369#[derive(Debug, Clone)]
370pub struct DataSegment {
371 pub index: MemoryIndex,
372 pub offset: InitExpr,
373 pub data: Vec<u8>,
374}
375
376impl Dump for DataSegment {
377 fn dump(&self, buf: &mut Vec<u8>) -> usize {
378 let mut size = 0;
379
380 let data = &self.data;
381
382 size += write_varuint32(buf, *self.index);
383 size += self.offset.dump(buf);
384
385 size += write_varuint32(buf, data.len() as u32);
386 size += write_slice(buf, data);
387
388 size
389 }
390}