web_assembler/
module.rs

1use util::*;
2use types::*;
3use Dump;
4
5#[derive(Debug, Clone)]
6pub struct Module {
7    //    version: usize
8    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}