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
25fn 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}