june_lang/
emitter.rs

1use crate::wasm::*;
2use leb128;
3use std::io;
4use std::io::Write;
5use std::result;
6use thiserror::Error;
7
8#[derive(Debug, Error)]
9pub enum Error {
10    #[error("io: {0}")]
11    IOError(#[from] io::Error),
12    #[error("vector too long: max len 2^32, found {0}")]
13    LengthError(usize),
14}
15
16pub type Result<T> = result::Result<T, Error>;
17
18const HEADER: &[u8] = &[0x00, 0x61, 0x73, 0x6d];
19const VERSION: &[u8] = &[0x01, 0x00, 0x00, 0x00];
20
21trait Writable<W: Write> {
22    fn write(&self, w: &mut W) -> Result<()>;
23}
24
25// https://webassembly.github.io/spec/core/binary/index.html
26
27fn write_len<W: Write>(w: &mut W, len: usize) -> Result<()> {
28    let len: u32 = len.try_into().or(Err(Error::LengthError(len)))?;
29    len.write(w)?;
30    Ok(())
31}
32
33fn vec<W: Write, T: Writable<W>>(w: &mut W, v: &[T]) -> Result<()> {
34    write_len(w, v.len())?;
35    for item in v {
36        item.write(w)?;
37    }
38    Ok(())
39}
40
41impl<W: Write> Writable<W> for u32 {
42    fn write(&self, w: &mut W) -> Result<()> {
43        leb128::write::unsigned(w, *self as u64)?;
44        Ok(())
45    }
46}
47
48impl<W: Write> Writable<W> for i64 {
49    fn write(&self, w: &mut W) -> Result<()> {
50        leb128::write::signed(w, *self)?;
51        Ok(())
52    }
53}
54
55impl<W: Write> Writable<W> for ValType {
56    fn write(&self, w: &mut W) -> Result<()> {
57        match self {
58            ValType::NumType(NumType::I64) => w.write_all(&[0x7E])?,
59        }
60        Ok(())
61    }
62}
63
64impl<W: Write> Writable<W> for FuncType {
65    fn write(&self, w: &mut W) -> Result<()> {
66        w.write_all(&[0x60])?;
67        vec(w, &self.params)?;
68        vec(w, &self.results)?;
69        Ok(())
70    }
71}
72
73impl<W: Write> Writable<W> for Func {
74    fn write(&self, w: &mut W) -> Result<()> {
75        self.typeidx.write(w)?;
76        Ok(())
77    }
78}
79
80impl<W: Write> Writable<W> for Const {
81    fn write(&self, w: &mut W) -> Result<()> {
82        match self {
83            Const::I64(x) => {
84                w.write_all(&[0x42])?;
85                x.write(w)?;
86            }
87        }
88        Ok(())
89    }
90}
91
92impl<W: Write> Writable<W> for Instr {
93    fn write(&self, w: &mut W) -> Result<()> {
94        match self {
95            Instr::End => w.write_all(&[0x0B])?,
96            Instr::Drop => w.write_all(&[0x1A])?,
97            Instr::AddI64 => w.write_all(&[0x7C])?,
98            Instr::SubI64 => w.write_all(&[0x7D])?,
99            Instr::Const(val) => val.write(w)?,
100            Instr::Call(idx) => {
101                w.write_all(&[0x10])?;
102                idx.write(w)?;
103            }
104            Instr::SetLocal(idx) => {
105                w.write_all(&[0x21])?;
106                idx.write(w)?;
107            }
108            Instr::GetLocal(idx) => {
109                w.write_all(&[0x20])?;
110                idx.write(w)?;
111            }
112        }
113        Ok(())
114    }
115}
116
117impl<W: Write> Writable<W> for Code {
118    fn write(&self, w: &mut W) -> Result<()> {
119        let mut buf = Vec::new();
120        vec(&mut buf, &self.locals)?;
121        for instr in &self.body {
122            instr.write(&mut buf)?;
123        }
124        write_len(w, buf.len())?;
125        w.write_all(&buf)?;
126        Ok(())
127    }
128}
129
130impl<W: Write> Writable<W> for String {
131    fn write(&self, w: &mut W) -> Result<()> {
132        write_len(w, self.len())?;
133        w.write_all(self.as_bytes())?;
134        Ok(())
135    }
136}
137
138impl<W: Write> Writable<W> for Export {
139    fn write(&self, w: &mut W) -> Result<()> {
140        self.name.write(w)?;
141        match self.desc {
142            ExportDesc::Func(idx) => {
143                w.write_all(&[0x00])?;
144                idx.write(w)?;
145            }
146        }
147        Ok(())
148    }
149}
150
151impl<W: Write> Writable<W> for Import {
152    fn write(&self, w: &mut W) -> Result<()> {
153        self.module.write(w)?;
154        self.name.write(w)?;
155        match self.import {
156            ImportedValue::Func(idx) => {
157                w.write_all(&[0x00])?;
158                idx.write(w)?;
159            }
160        }
161        Ok(())
162    }
163}
164
165#[derive(Debug)]
166pub enum Section {
167    Type(TypeSection),
168    Import(ImportSection),
169    Func(FuncSection),
170    Export(ExportSection),
171    Code(CodeSection),
172    Start(StartSection),
173}
174
175fn section_index(section: &Section) -> u8 {
176    match section {
177        Section::Type(_) => 1,
178        Section::Import(_) => 2,
179        Section::Func(_) => 3,
180        Section::Export(_) => 7,
181        Section::Start(_) => 8,
182        Section::Code(_) => 10,
183    }
184}
185
186impl<W: Write> Writable<W> for Section {
187    fn write(&self, w: &mut W) -> Result<()> {
188        w.write_all(&[section_index(self)])?;
189        let mut buf = Vec::new();
190        match self {
191            Section::Type(types) => vec(&mut buf, &types.0)?,
192            Section::Import(imports) => vec(&mut buf, &imports.0)?,
193            Section::Func(funcs) => vec(&mut buf, &funcs.0)?,
194            Section::Export(exports) => vec(&mut buf, &exports.0)?,
195            Section::Start(start) => start.0.write(&mut buf)?,
196            Section::Code(code) => vec(&mut buf, &code.0)?,
197        }
198        write_len(w, buf.len())?;
199        w.write_all(&buf)?;
200        Ok(())
201    }
202}
203
204pub fn emit<W: Write>(w: &mut W, module: Module) -> Result<()> {
205    w.write_all(HEADER)?;
206    w.write_all(VERSION)?;
207    Section::Type(module.types).write(w)?;
208    Section::Import(module.imports).write(w)?;
209    Section::Func(module.funcs).write(w)?;
210    Section::Export(module.exports).write(w)?;
211    Section::Start(module.start).write(w)?;
212    Section::Code(module.code).write(w)?;
213    Ok(())
214}