wit_writer/
lib.rs

1//! A crate to write the raw wasm interface types section.
2
3#![deny(missing_docs)]
4
5use std::mem;
6
7/// A structure used to write out the raw representation of a wasm interface
8/// types subsection.
9///
10/// This type performs no validation as items are written, but if you're just
11/// calling the methods of this writer you should always produce a syntatically
12/// valid section at least.
13pub struct Writer {
14    dst: Vec<u8>,
15    tmp: Vec<Vec<u8>>,
16}
17
18impl Writer {
19    /// Returns a new `Writer` ready for encoding a wasm interface types section.
20    pub fn new() -> Writer {
21        let mut w = Writer {
22            dst: Vec::new(),
23            tmp: Vec::new(),
24        };
25        wit_schema_version::VERSION.encode(&mut w.dst);
26        return w;
27    }
28
29    /// Returns a section writer used to write out the type subsection of a
30    /// wasm interface types section.
31    pub fn types(&mut self, cnt: u32) -> Types<'_> {
32        Types {
33            tmp: self.start_section(cnt),
34            dst: self,
35        }
36    }
37
38    /// Returns a section writer used to write out the import subsection of a
39    /// wasm interface types section.
40    pub fn imports(&mut self, cnt: u32) -> Imports<'_> {
41        Imports {
42            tmp: self.start_section(cnt),
43            dst: self,
44        }
45    }
46
47    /// Returns a section writer used to write out the function subsection of a
48    /// wasm interface types section.
49    pub fn funcs(&mut self, cnt: u32) -> Funcs<'_> {
50        Funcs {
51            tmp: self.start_section(cnt),
52            dst: self,
53        }
54    }
55
56    /// Returns a section writer used to write out the export subsection of a
57    /// wasm interface types section.
58    pub fn exports(&mut self, cnt: u32) -> Exports<'_> {
59        Exports {
60            tmp: self.start_section(cnt),
61            dst: self,
62        }
63    }
64
65    /// Returns a section writer used to write out the implements subsection of a
66    /// wasm interface types section.
67    pub fn implements(&mut self, cnt: u32) -> Implements<'_> {
68        Implements {
69            tmp: self.start_section(cnt),
70            dst: self,
71        }
72    }
73
74    /// Consumes this writer, returning all bytes written so far.
75    ///
76    /// This will only return the payload of the wasm interface types custom
77    /// section, not the custom section headers.
78    pub fn into_payload(self) -> Vec<u8> {
79        self.dst
80    }
81
82    /// Consumes this writer, returning all bytes written so far.
83    pub fn into_custom_section(mut self) -> Vec<u8> {
84        let mut tmp = self.pop_tmp();
85        wit_schema_version::SECTION_NAME.encode(&mut tmp);
86        tmp.extend_from_slice(&self.dst);
87        let mut tmp2 = self.pop_tmp();
88        tmp2.push(0);
89        tmp.encode(&mut tmp2);
90        return tmp2;
91    }
92
93    fn pop_tmp(&mut self) -> Vec<u8> {
94        self.tmp.pop().unwrap_or(Vec::new())
95    }
96
97    fn push_tmp(&mut self, mut tmp: Vec<u8>) {
98        tmp.truncate(0);
99        self.tmp.push(tmp);
100    }
101
102    fn start_section(&mut self, cnt: u32) -> Vec<u8> {
103        let mut buf = self.pop_tmp();
104        if cnt > 0 {
105            cnt.encode(&mut buf);
106        }
107        buf
108    }
109
110    fn finish_section(&mut self, id: u8, data: Vec<u8>) {
111        if data.len() > 0 {
112            self.dst.push(id);
113            data.encode(&mut self.dst);
114        }
115        self.push_tmp(data);
116    }
117}
118
119/// Writer for the list of types in a type subsection.
120pub struct Types<'a> {
121    dst: &'a mut Writer,
122    tmp: Vec<u8>,
123}
124
125impl Types<'_> {
126    /// Adds a new type in this type section.
127    ///
128    /// The `nparams` argument specifies how many types will be written by the
129    /// `params` closure, and the `nresults argument lists how many times the
130    /// `results` closure will write out a type.
131    ///
132    /// # Panics
133    ///
134    /// Panics if `params` or `results` doesn't write out the same number of
135    /// types that are specified.
136    pub fn add(
137        &mut self,
138        nparams: u32,
139        params: impl FnOnce(&mut Type<'_>),
140        nresults: u32,
141        results: impl FnOnce(&mut Type<'_>),
142    ) {
143        let mut t = Type {
144            dst: &mut self.tmp,
145            cnt: 0,
146        };
147        nparams.encode(t.dst);
148        params(&mut t);
149        assert_eq!(nparams, t.cnt);
150        t.cnt = 0;
151        nresults.encode(t.dst);
152        results(&mut t);
153        assert_eq!(nresults, t.cnt);
154    }
155}
156
157impl Drop for Types<'_> {
158    fn drop(&mut self) {
159        self.dst
160            .finish_section(0x00, mem::replace(&mut self.tmp, Vec::new()));
161    }
162}
163
164/// A writer to write out a type, or a sequence of types.
165pub struct Type<'a> {
166    cnt: u32,
167    dst: &'a mut Vec<u8>,
168}
169
170#[allow(missing_docs)]
171#[rustfmt::skip]
172impl Type<'_> {
173    fn ty(&mut self, byte: u8) {
174        self.cnt += 1;
175        self.dst.push(byte);
176    }
177
178    pub fn s8(&mut self) { self.ty(0x00) }
179    pub fn s16(&mut self) { self.ty(0x01) }
180    pub fn s32(&mut self) { self.ty(0x02) }
181    pub fn s64(&mut self) { self.ty(0x03) }
182    pub fn u8(&mut self) { self.ty(0x04) }
183    pub fn u16(&mut self) { self.ty(0x05) }
184    pub fn u32(&mut self) { self.ty(0x06) }
185    pub fn u64(&mut self) { self.ty(0x07) }
186    pub fn f32(&mut self) { self.ty(0x08) }
187    pub fn f64(&mut self) { self.ty(0x09) }
188    pub fn string(&mut self) { self.ty(0x0a) }
189    pub fn externref(&mut self) { self.ty(0x0b) }
190    pub fn i32(&mut self) { self.ty(0x0c) }
191    pub fn i64(&mut self) { self.ty(0x0d) }
192}
193
194/// Writer for the list of imports in an import subsection.
195pub struct Imports<'a> {
196    dst: &'a mut Writer,
197    tmp: Vec<u8>,
198}
199
200impl Imports<'_> {
201    /// Adds a new import in this type section.
202    pub fn add(&mut self, module: &str, name: &str, ty: u32) {
203        module.encode(&mut self.tmp);
204        name.encode(&mut self.tmp);
205        ty.encode(&mut self.tmp);
206    }
207}
208
209impl Drop for Imports<'_> {
210    fn drop(&mut self) {
211        self.dst
212            .finish_section(0x01, mem::replace(&mut self.tmp, Vec::new()));
213    }
214}
215
216/// Writer for the list of functions in an function subsection.
217pub struct Funcs<'a> {
218    dst: &'a mut Writer,
219    tmp: Vec<u8>,
220}
221
222impl<'a> Funcs<'a> {
223    /// Adds a new function in this type section.
224    pub fn add(&mut self, ty: u32) -> Instructions<'a, '_> {
225        let mut dst = self.dst.pop_tmp();
226        ty.encode(&mut dst);
227        Instructions {
228            tmp: dst,
229            funcs: self,
230        }
231    }
232}
233
234impl Drop for Funcs<'_> {
235    fn drop(&mut self) {
236        self.dst
237            .finish_section(0x02, mem::replace(&mut self.tmp, Vec::new()));
238    }
239}
240
241/// Writer for a sequence of instructions in a function subsection
242pub struct Instructions<'a, 'b> {
243    tmp: Vec<u8>,
244    funcs: &'b mut Funcs<'a>,
245}
246
247#[allow(missing_docs)]
248#[rustfmt::skip]
249impl Instructions<'_, '_> {
250    pub fn arg_get(&mut self, arg: u32) {
251        self.tmp.push(0x00);
252        arg.encode(&mut self.tmp);
253    }
254
255    pub fn call_core(&mut self, func: u32) {
256        self.tmp.push(0x01);
257        func.encode(&mut self.tmp);
258    }
259
260    pub fn memory_to_string(&mut self, mem: u32) {
261        self.tmp.push(0x03);
262        mem.encode(&mut self.tmp);
263    }
264
265    pub fn string_to_memory(&mut self, malloc: u32, mem: u32) {
266        self.tmp.push(0x04);
267        malloc.encode(&mut self.tmp);
268        mem.encode(&mut self.tmp);
269    }
270
271    pub fn call_adapter(&mut self, func: u32) {
272        self.tmp.push(0x05);
273        func.encode(&mut self.tmp);
274    }
275
276    pub fn defer_call_core(&mut self, func: u32) {
277        self.tmp.push(0x06);
278        func.encode(&mut self.tmp);
279    }
280
281    pub fn i32_to_s8(&mut self) { self.tmp.push(0x07) }
282    pub fn i32_to_s8x(&mut self) { self.tmp.push(0x08) }
283    pub fn i32_to_u8(&mut self) { self.tmp.push(0x09) }
284    pub fn i32_to_s16(&mut self) { self.tmp.push(0x0a) }
285    pub fn i32_to_s16x(&mut self) { self.tmp.push(0x0b) }
286    pub fn i32_to_u16(&mut self) { self.tmp.push(0x0c) }
287    pub fn i32_to_s32(&mut self) { self.tmp.push(0x0d) }
288    pub fn i32_to_u32(&mut self) { self.tmp.push(0x0e) }
289    pub fn i32_to_s64(&mut self) { self.tmp.push(0x0f) }
290    pub fn i32_to_u64(&mut self) { self.tmp.push(0x10) }
291
292    pub fn i64_to_s8(&mut self) { self.tmp.push(0x11) }
293    pub fn i64_to_s8x(&mut self) { self.tmp.push(0x12) }
294    pub fn i64_to_u8(&mut self) { self.tmp.push(0x13) }
295    pub fn i64_to_s16(&mut self) { self.tmp.push(0x14) }
296    pub fn i64_to_s16x(&mut self) { self.tmp.push(0x15) }
297    pub fn i64_to_u16(&mut self) { self.tmp.push(0x16) }
298    pub fn i64_to_s32(&mut self) { self.tmp.push(0x17) }
299    pub fn i64_to_s32x(&mut self) { self.tmp.push(0x18) }
300    pub fn i64_to_u32(&mut self) { self.tmp.push(0x19) }
301    pub fn i64_to_s64(&mut self) { self.tmp.push(0x1a) }
302    pub fn i64_to_u64(&mut self) { self.tmp.push(0x1b) }
303
304    pub fn s8_to_i32(&mut self) { self.tmp.push(0x1c) }
305    pub fn u8_to_i32(&mut self) { self.tmp.push(0x1d) }
306    pub fn s16_to_i32(&mut self) { self.tmp.push(0x1e) }
307    pub fn u16_to_i32(&mut self) { self.tmp.push(0x1f) }
308    pub fn s32_to_i32(&mut self) { self.tmp.push(0x20) }
309    pub fn u32_to_i32(&mut self) { self.tmp.push(0x21) }
310    pub fn s64_to_i32(&mut self) { self.tmp.push(0x22) }
311    pub fn s64_to_i32x(&mut self) { self.tmp.push(0x23) }
312    pub fn u64_to_i32(&mut self) { self.tmp.push(0x24) }
313    pub fn u64_to_i32x(&mut self) { self.tmp.push(0x25) }
314
315    pub fn s8_to_i64(&mut self) { self.tmp.push(0x26) }
316    pub fn u8_to_i64(&mut self) { self.tmp.push(0x27) }
317    pub fn s16_to_i64(&mut self) { self.tmp.push(0x28) }
318    pub fn u16_to_i64(&mut self) { self.tmp.push(0x29) }
319    pub fn s32_to_i64(&mut self) { self.tmp.push(0x2a) }
320    pub fn u32_to_i64(&mut self) { self.tmp.push(0x2b) }
321    pub fn s64_to_i64(&mut self) { self.tmp.push(0x2c) }
322    pub fn u64_to_i64(&mut self) { self.tmp.push(0x2d) }
323}
324
325impl Drop for Instructions<'_, '_> {
326    fn drop(&mut self) {
327        self.tmp.push(0x02);
328        let buf = mem::replace(&mut self.tmp, Vec::new());
329        buf.encode(&mut self.funcs.tmp);
330        self.funcs.dst.push_tmp(buf);
331    }
332}
333
334/// Writer for the list of exports in an export subsection.
335pub struct Exports<'a> {
336    dst: &'a mut Writer,
337    tmp: Vec<u8>,
338}
339
340impl Exports<'_> {
341    /// Adds a new export in this type section.
342    pub fn add(&mut self, name: &str, func: u32) {
343        func.encode(&mut self.tmp);
344        name.encode(&mut self.tmp);
345    }
346}
347
348impl Drop for Exports<'_> {
349    fn drop(&mut self) {
350        self.dst
351            .finish_section(0x03, mem::replace(&mut self.tmp, Vec::new()));
352    }
353}
354
355/// Writer for the list of imports in an import subsection.
356pub struct Implements<'a> {
357    dst: &'a mut Writer,
358    tmp: Vec<u8>,
359}
360
361impl Implements<'_> {
362    /// Adds a new import in this type section.
363    pub fn add(&mut self, core_func: u32, adapter_func: u32) {
364        core_func.encode(&mut self.tmp);
365        adapter_func.encode(&mut self.tmp);
366    }
367}
368
369impl Drop for Implements<'_> {
370    fn drop(&mut self) {
371        self.dst
372            .finish_section(0x04, mem::replace(&mut self.tmp, Vec::new()));
373    }
374}
375
376trait Encode {
377    fn encode(&self, e: &mut Vec<u8>);
378}
379
380impl Encode for [u8] {
381    fn encode(&self, e: &mut Vec<u8>) {
382        self.len().encode(e);
383        e.extend_from_slice(self);
384    }
385}
386
387impl Encode for str {
388    fn encode(&self, e: &mut Vec<u8>) {
389        self.as_bytes().encode(e);
390    }
391}
392
393impl Encode for usize {
394    fn encode(&self, e: &mut Vec<u8>) {
395        assert!(*self <= u32::max_value() as usize);
396        (*self as u32).encode(e)
397    }
398}
399
400impl Encode for u32 {
401    fn encode(&self, e: &mut Vec<u8>) {
402        leb128::write::unsigned(e, (*self).into()).unwrap();
403    }
404}