wasmer_interface_types/encoders/
binary.rs

1//! Writes the AST into bytes representing WIT with its binary format.
2
3use crate::{ast::*, interpreter::Instruction, types::*};
4use std::io::{self, Write};
5
6/// A trait for converting a value to bytes.
7pub trait ToBytes<W>
8where
9    W: Write,
10{
11    /// Converts the given value into `&[u8]` in the given `writer`.
12    fn to_bytes(&self, writer: &mut W) -> io::Result<()>;
13}
14
15/// Encode a `u8` into a byte (well, it's already a byte!).
16impl<W> ToBytes<W> for u8
17where
18    W: Write,
19{
20    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
21        writer.write_all(&[*self])
22    }
23}
24
25/// Encode a `u64` into bytes with a LEB128 representation.
26///
27/// Decoder is `decoders::binary::uleb`.
28impl<W> ToBytes<W> for u64
29where
30    W: Write,
31{
32    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
33        let mut value = *self;
34
35        // Code adapted from the Rust' `serialize` library.
36        loop {
37            if value < 0x80 {
38                writer.write_all(&[value as u8])?;
39
40                break;
41            }
42
43            writer.write_all(&[((value & 0x7f) | 0x80) as u8])?;
44            value >>= 7;
45        }
46
47        Ok(())
48    }
49}
50
51/// Encode a `str` into bytes.
52///
53/// Decoder is `decoders::binary::string`.
54impl<W> ToBytes<W> for &str
55where
56    W: Write,
57{
58    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
59        // Size first.
60        writer.write_all(&[self.len() as u8])?;
61
62        // Then the string.
63        writer.write_all(self.as_bytes())?;
64
65        Ok(())
66    }
67}
68
69/// Encode a vector into bytes.
70///
71/// Decoder is `decoders::binary::list`.
72impl<W, I> ToBytes<W> for Vec<I>
73where
74    W: Write,
75    I: ToBytes<W>,
76{
77    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
78        // Size first.
79        (self.len() as u64).to_bytes(writer)?;
80
81        // Then the items.
82        for item in self {
83            item.to_bytes(writer)?;
84        }
85
86        Ok(())
87    }
88}
89
90/// Encode an `InterfaceType` into bytes.
91impl<W> ToBytes<W> for InterfaceType
92where
93    W: Write,
94{
95    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
96        match self {
97            InterfaceType::S8 => 0x00_u8.to_bytes(writer),
98            InterfaceType::S16 => 0x01_u8.to_bytes(writer),
99            InterfaceType::S32 => 0x02_u8.to_bytes(writer),
100            InterfaceType::S64 => 0x03_u8.to_bytes(writer),
101            InterfaceType::U8 => 0x04_u8.to_bytes(writer),
102            InterfaceType::U16 => 0x05_u8.to_bytes(writer),
103            InterfaceType::U32 => 0x06_u8.to_bytes(writer),
104            InterfaceType::U64 => 0x07_u8.to_bytes(writer),
105            InterfaceType::F32 => 0x08_u8.to_bytes(writer),
106            InterfaceType::F64 => 0x09_u8.to_bytes(writer),
107            InterfaceType::String => 0x0a_u8.to_bytes(writer),
108            InterfaceType::Anyref => 0x0b_u8.to_bytes(writer),
109            InterfaceType::I32 => 0x0c_u8.to_bytes(writer),
110            InterfaceType::I64 => 0x0d_u8.to_bytes(writer),
111            InterfaceType::Record(record_type) => {
112                0x0e_u8.to_bytes(writer)?;
113                record_type.to_bytes(writer)
114            }
115        }
116    }
117}
118
119/// Encode a `RecordType` into bytes.
120impl<W> ToBytes<W> for RecordType
121where
122    W: Write,
123{
124    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
125        self.fields.to_bytes(writer)
126    }
127}
128
129/// Encode a `TypeKind` into bytes.
130impl<W> ToBytes<W> for TypeKind
131where
132    W: Write,
133{
134    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
135        match self {
136            TypeKind::Function => 0x00_u8.to_bytes(writer),
137            TypeKind::Record => 0x01_u8.to_bytes(writer),
138        }
139    }
140}
141
142/// Encode an `InterfaceKind` into bytes.
143impl<W> ToBytes<W> for InterfaceKind
144where
145    W: Write,
146{
147    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
148        match self {
149            Self::Type => 0x00_u8.to_bytes(writer),
150            Self::Import => 0x01_u8.to_bytes(writer),
151            Self::Adapter => 0x02_u8.to_bytes(writer),
152            Self::Export => 0x03_u8.to_bytes(writer),
153            Self::Implementation => 0x04_u8.to_bytes(writer),
154        }
155    }
156}
157
158/// Encode a `Type` into bytes.
159///
160/// Decoder is in `decoders::binary::types`.
161impl<W> ToBytes<W> for Type
162where
163    W: Write,
164{
165    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
166        match self {
167            Type::Function { inputs, outputs } => {
168                TypeKind::Function.to_bytes(writer)?;
169                inputs.to_bytes(writer)?;
170                outputs.to_bytes(writer)?;
171            }
172
173            Type::Record(record_type) => {
174                TypeKind::Record.to_bytes(writer)?;
175                record_type.to_bytes(writer)?;
176            }
177        }
178
179        Ok(())
180    }
181}
182
183/// Encode an `Import` into bytes.
184///
185/// Decoder is in `decoders::binary::imports`.
186impl<W> ToBytes<W> for Import<'_>
187where
188    W: Write,
189{
190    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
191        self.namespace.to_bytes(writer)?;
192        self.name.to_bytes(writer)?;
193        (self.signature_type as u64).to_bytes(writer)?;
194
195        Ok(())
196    }
197}
198
199/// Encode an `Adapter` into bytes.
200///
201/// Decoder is in `decoders::binary::adapters`.
202impl<W> ToBytes<W> for Adapter
203where
204    W: Write,
205{
206    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
207        (self.function_type as u64).to_bytes(writer)?;
208        self.instructions.to_bytes(writer)?;
209
210        Ok(())
211    }
212}
213
214/// Encode an `Export` into bytes.
215///
216/// Decoder is in `decoders::binary::exports`.
217impl<W> ToBytes<W> for Export<'_>
218where
219    W: Write,
220{
221    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
222        self.name.to_bytes(writer)?;
223        (self.function_type as u64).to_bytes(writer)?;
224
225        Ok(())
226    }
227}
228
229/// Encode an `Implementation` into bytes.
230///
231/// Decoder is in `decoders::binary::implementations`.
232impl<W> ToBytes<W> for Implementation
233where
234    W: Write,
235{
236    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
237        (self.core_function_type as u64).to_bytes(writer)?;
238        (self.adapter_function_type as u64).to_bytes(writer)?;
239
240        Ok(())
241    }
242}
243
244/// Encode an `Interfaces` into bytes.
245///
246/// Decoder is `decoders::binary::parse`.
247impl<W> ToBytes<W> for Interfaces<'_>
248where
249    W: Write,
250{
251    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
252        if !self.types.is_empty() {
253            InterfaceKind::Type.to_bytes(writer)?;
254            self.types.to_bytes(writer)?;
255        }
256
257        if !self.imports.is_empty() {
258            InterfaceKind::Import.to_bytes(writer)?;
259            self.imports.to_bytes(writer)?;
260        }
261
262        if !self.adapters.is_empty() {
263            InterfaceKind::Adapter.to_bytes(writer)?;
264            self.adapters.to_bytes(writer)?;
265        }
266
267        if !self.exports.is_empty() {
268            InterfaceKind::Export.to_bytes(writer)?;
269            self.exports.to_bytes(writer)?;
270        }
271
272        if !self.implementations.is_empty() {
273            InterfaceKind::Implementation.to_bytes(writer)?;
274            self.implementations.to_bytes(writer)?;
275        }
276
277        Ok(())
278    }
279}
280
281/// Encode an `Instruction` into bytes.
282///
283/// Decoder is `decoders::binary::instruction`.
284impl<W> ToBytes<W> for Instruction
285where
286    W: Write,
287{
288    fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
289        match self {
290            Instruction::ArgumentGet { index } => {
291                0x00_u8.to_bytes(writer)?;
292                (*index as u64).to_bytes(writer)?;
293            }
294
295            Instruction::CallCore { function_index } => {
296                0x01_u8.to_bytes(writer)?;
297                (*function_index as u64).to_bytes(writer)?;
298            }
299
300            Instruction::S8FromI32 => 0x02_u8.to_bytes(writer)?,
301            Instruction::S8FromI64 => 0x03_u8.to_bytes(writer)?,
302            Instruction::S16FromI32 => 0x04_u8.to_bytes(writer)?,
303            Instruction::S16FromI64 => 0x05_u8.to_bytes(writer)?,
304            Instruction::S32FromI32 => 0x06_u8.to_bytes(writer)?,
305            Instruction::S32FromI64 => 0x07_u8.to_bytes(writer)?,
306            Instruction::S64FromI32 => 0x08_u8.to_bytes(writer)?,
307            Instruction::S64FromI64 => 0x09_u8.to_bytes(writer)?,
308            Instruction::I32FromS8 => 0x0a_u8.to_bytes(writer)?,
309            Instruction::I32FromS16 => 0x0b_u8.to_bytes(writer)?,
310            Instruction::I32FromS32 => 0x0c_u8.to_bytes(writer)?,
311            Instruction::I32FromS64 => 0x0d_u8.to_bytes(writer)?,
312            Instruction::I64FromS8 => 0x0e_u8.to_bytes(writer)?,
313            Instruction::I64FromS16 => 0x0f_u8.to_bytes(writer)?,
314            Instruction::I64FromS32 => 0x10_u8.to_bytes(writer)?,
315            Instruction::I64FromS64 => 0x11_u8.to_bytes(writer)?,
316            Instruction::U8FromI32 => 0x12_u8.to_bytes(writer)?,
317            Instruction::U8FromI64 => 0x13_u8.to_bytes(writer)?,
318            Instruction::U16FromI32 => 0x14_u8.to_bytes(writer)?,
319            Instruction::U16FromI64 => 0x15_u8.to_bytes(writer)?,
320            Instruction::U32FromI32 => 0x16_u8.to_bytes(writer)?,
321            Instruction::U32FromI64 => 0x17_u8.to_bytes(writer)?,
322            Instruction::U64FromI32 => 0x18_u8.to_bytes(writer)?,
323            Instruction::U64FromI64 => 0x19_u8.to_bytes(writer)?,
324            Instruction::I32FromU8 => 0x1a_u8.to_bytes(writer)?,
325            Instruction::I32FromU16 => 0x1b_u8.to_bytes(writer)?,
326            Instruction::I32FromU32 => 0x1c_u8.to_bytes(writer)?,
327            Instruction::I32FromU64 => 0x1d_u8.to_bytes(writer)?,
328            Instruction::I64FromU8 => 0x1e_u8.to_bytes(writer)?,
329            Instruction::I64FromU16 => 0x1f_u8.to_bytes(writer)?,
330            Instruction::I64FromU32 => 0x20_u8.to_bytes(writer)?,
331            Instruction::I64FromU64 => 0x21_u8.to_bytes(writer)?,
332
333            Instruction::StringLiftMemory => 0x22_u8.to_bytes(writer)?,
334            Instruction::StringLowerMemory => 0x23_u8.to_bytes(writer)?,
335            Instruction::StringSize => 0x24_u8.to_bytes(writer)?,
336
337            Instruction::RecordLift { type_index } => {
338                0x25_u8.to_bytes(writer)?;
339                (*type_index as u64).to_bytes(writer)?
340            }
341            Instruction::RecordLower { type_index } => {
342                0x26_u8.to_bytes(writer)?;
343                (*type_index as u64).to_bytes(writer)?
344            }
345        }
346
347        Ok(())
348    }
349}
350
351#[cfg(test)]
352mod tests {
353    use super::*;
354
355    macro_rules! assert_to_bytes {
356        ($expr:expr, $expected_output:expr) => {{
357            let mut output = vec![];
358
359            $expr.to_bytes(&mut output).expect(concat!(
360                "Unable to encode the expression `",
361                stringify!($expr),
362                "` to bytes."
363            ));
364
365            assert_eq!(output.as_slice(), &$expected_output[..]);
366        }};
367    }
368
369    #[test]
370    fn test_u8() {
371        assert_to_bytes!(0x01_u8, &[0x01]);
372    }
373
374    #[test]
375    fn test_uleb_1_byte() {
376        assert_to_bytes!(0x01_u64, &[0x01]);
377    }
378
379    #[test]
380    fn test_uleb_3_bytes() {
381        assert_to_bytes!(0x7ffc_u64, &[0xfc, 0xff, 0x01]);
382    }
383
384    // Examples from Figure 22 of [DWARF 4
385    // standard](http://dwarfstd.org/doc/DWARF4.pdf).
386    #[test]
387    fn test_uleb_from_dward_standard() {
388        assert_to_bytes!(2u64, &[2u8]);
389        assert_to_bytes!(127u64, &[127u8]);
390        assert_to_bytes!(128u64, &[0x80, 1u8]);
391        assert_to_bytes!(129u64, &[1u8 | 0x80, 1]);
392        assert_to_bytes!(130u64, &[2u8 | 0x80, 1]);
393        assert_to_bytes!(12857u64, &[57u8 | 0x80, 100]);
394    }
395
396    #[test]
397    fn test_empty_str() {
398        assert_to_bytes!("", &[0x00]);
399    }
400
401    #[test]
402    fn test_str() {
403        assert_to_bytes!("abc", &[0x03, 0x61, 0x62, 0x63]);
404    }
405
406    #[test]
407    fn test_empty_vec() {
408        assert_to_bytes!(Vec::<u8>::new(), &[0x00]);
409    }
410
411    #[test]
412    fn test_vec() {
413        assert_to_bytes!(
414            vec!["a", "b", "c"],
415            &[
416                0x03, // list of 3 items
417                0x01, // string of 1 byte
418                0x61, // "a"
419                0x01, // string of 1 byte
420                0x62, // "b"
421                0x01, // string of 1 byte
422                0x63, // "c"
423            ]
424        );
425    }
426
427    #[test]
428    fn test_interface_type() {
429        assert_to_bytes!(InterfaceType::S8, &[0x00]);
430        assert_to_bytes!(InterfaceType::S16, &[0x01]);
431        assert_to_bytes!(InterfaceType::S32, &[0x02]);
432        assert_to_bytes!(InterfaceType::S64, &[0x03]);
433        assert_to_bytes!(InterfaceType::U8, &[0x04]);
434        assert_to_bytes!(InterfaceType::U16, &[0x05]);
435        assert_to_bytes!(InterfaceType::U32, &[0x06]);
436        assert_to_bytes!(InterfaceType::U64, &[0x07]);
437        assert_to_bytes!(InterfaceType::F32, &[0x08]);
438        assert_to_bytes!(InterfaceType::F64, &[0x09]);
439        assert_to_bytes!(InterfaceType::String, &[0x0a]);
440        assert_to_bytes!(InterfaceType::Anyref, &[0x0b]);
441        assert_to_bytes!(InterfaceType::I32, &[0x0c]);
442        assert_to_bytes!(InterfaceType::I64, &[0x0d]);
443        assert_to_bytes!(
444            InterfaceType::Record(RecordType {
445                fields: vec1![InterfaceType::String]
446            }),
447            &[0x0e, 0x01, 0x0a]
448        );
449    }
450
451    #[test]
452    fn test_record_type() {
453        assert_to_bytes!(
454            RecordType {
455                fields: vec1![InterfaceType::String]
456            },
457            &[
458                0x01, // 1 field
459                0x0a, // String
460            ]
461        );
462        assert_to_bytes!(
463            RecordType {
464                fields: vec1![InterfaceType::String, InterfaceType::I32]
465            },
466            &[
467                0x02, // 2 fields
468                0x0a, // String
469                0x0c, // I32
470            ]
471        );
472        assert_to_bytes!(
473            RecordType {
474                fields: vec1![
475                    InterfaceType::String,
476                    InterfaceType::Record(RecordType {
477                        fields: vec1![InterfaceType::I32, InterfaceType::I32],
478                    }),
479                    InterfaceType::F64,
480                ],
481            },
482            &[
483                0x03, // 3 fields
484                0x0a, // String
485                0x0e, // Record
486                0x02, // 2 fields
487                0x0c, // I32
488                0x0c, // I32
489                0x09, // F64
490            ]
491        );
492    }
493
494    #[test]
495    fn test_interface_kind() {
496        assert_to_bytes!(InterfaceKind::Type, &[0x00]);
497        assert_to_bytes!(InterfaceKind::Import, &[0x01]);
498        assert_to_bytes!(InterfaceKind::Adapter, &[0x02]);
499        assert_to_bytes!(InterfaceKind::Export, &[0x03]);
500        assert_to_bytes!(InterfaceKind::Implementation, &[0x04]);
501    }
502
503    #[test]
504    fn test_export() {
505        assert_to_bytes!(
506            Export {
507                name: "abc",
508                function_type: 0,
509            },
510            &[
511                0x03, // string of length 3
512                0x61, // "a"
513                0x62, // "b"
514                0x63, // "c"
515                0x00, // function type
516            ]
517        );
518    }
519
520    #[test]
521    fn test_type_function() {
522        assert_to_bytes!(
523            Type::Function {
524                inputs: vec![InterfaceType::I32, InterfaceType::I64],
525                outputs: vec![InterfaceType::S32],
526            },
527            &[
528                0x00, // function type
529                0x02, // list of 2 items
530                0x0c, // I32
531                0x0d, // I64
532                0x01, // list of 1 items
533                0x02, // I64
534            ]
535        );
536    }
537
538    #[test]
539    fn test_type_record() {
540        assert_to_bytes!(
541            Type::Record(RecordType {
542                fields: vec1![InterfaceType::I32, InterfaceType::I64],
543            }),
544            &[
545                0x01, // record type
546                0x02, // list of 2 items
547                0x0c, // I32
548                0x0d, // I64
549            ]
550        );
551    }
552
553    #[test]
554    fn test_import() {
555        assert_to_bytes!(
556            Import {
557                namespace: "a",
558                name: "b",
559                signature_type: 0,
560            },
561            &[
562                0x01, // string of length 1
563                0x61, // "a"
564                0x01, // string of length 1
565                0x62, // "b"
566                0x00, // signature typr
567            ]
568        );
569    }
570
571    #[test]
572    fn test_adapter() {
573        assert_to_bytes!(
574            Adapter {
575                function_type: 0,
576                instructions: vec![Instruction::ArgumentGet { index: 1 }],
577            },
578            &[
579                0x00, // function type
580                0x01, // list of 1 item
581                0x00, 0x01, // ArgumentGet { index: 1 }
582            ]
583        );
584    }
585
586    #[test]
587    fn test_interfaces() {
588        assert_to_bytes!(
589            Interfaces {
590                types: vec![Type::Function {
591                    inputs: vec![InterfaceType::S8],
592                    outputs: vec![InterfaceType::S16],
593                }],
594                imports: vec![Import {
595                    namespace: "ab",
596                    name: "c",
597                    signature_type: 0,
598                }],
599                adapters: vec![Adapter {
600                    function_type: 0,
601                    instructions: vec![Instruction::ArgumentGet { index: 1 }],
602                }],
603                exports: vec![Export {
604                    name: "ab",
605                    function_type: 1,
606                }],
607                implementations: vec![Implementation {
608                    core_function_type: 2,
609                    adapter_function_type: 3,
610                }],
611            },
612            &[
613                0x00, // type section
614                0x01, // 1 type
615                0x00, // function type
616                0x01, // list of 1 item
617                0x00, // S8
618                0x01, // list of 1 item
619                0x01, // S16
620                //
621                0x01, // import section
622                0x01, // 1 import
623                0x02, // string of 2 bytes
624                0x61, 0x62, // "a", "b"
625                0x01, // string of 1 byte
626                0x63, // "c"
627                0x00, // signature type
628                //
629                0x02, // adapter section
630                0x01, // 1 adapter
631                0x00, // function type
632                0x01, // list of 1 item
633                0x00, 0x01, // ArgumentGet { index: 1 }
634                //
635                0x03, // export section
636                0x01, // 1 export
637                0x02, // string of 2 bytes
638                0x61, 0x62, // "a", "b"
639                0x01, // function type
640                //
641                0x04, // implementation section
642                0x01, // 1 implementation
643                0x02, // core function type
644                0x03, // adapter function type
645            ]
646        );
647    }
648
649    #[test]
650    fn test_instructions() {
651        assert_to_bytes!(
652            vec![
653                Instruction::ArgumentGet { index: 1 },
654                Instruction::CallCore { function_index: 1 },
655                Instruction::S8FromI32,
656                Instruction::S8FromI64,
657                Instruction::S16FromI32,
658                Instruction::S16FromI64,
659                Instruction::S32FromI32,
660                Instruction::S32FromI64,
661                Instruction::S64FromI32,
662                Instruction::S64FromI64,
663                Instruction::I32FromS8,
664                Instruction::I32FromS16,
665                Instruction::I32FromS32,
666                Instruction::I32FromS64,
667                Instruction::I64FromS8,
668                Instruction::I64FromS16,
669                Instruction::I64FromS32,
670                Instruction::I64FromS64,
671                Instruction::U8FromI32,
672                Instruction::U8FromI64,
673                Instruction::U16FromI32,
674                Instruction::U16FromI64,
675                Instruction::U32FromI32,
676                Instruction::U32FromI64,
677                Instruction::U64FromI32,
678                Instruction::U64FromI64,
679                Instruction::I32FromU8,
680                Instruction::I32FromU16,
681                Instruction::I32FromU32,
682                Instruction::I32FromU64,
683                Instruction::I64FromU8,
684                Instruction::I64FromU16,
685                Instruction::I64FromU32,
686                Instruction::I64FromU64,
687                Instruction::StringLiftMemory,
688                Instruction::StringLowerMemory,
689                Instruction::StringSize,
690                Instruction::RecordLift { type_index: 1 },
691                Instruction::RecordLower { type_index: 1 },
692            ],
693            &[
694                0x27, // list of 39 items
695                0x00, 0x01, // ArgumentGet { index: 1 }
696                0x01, 0x01, // CallCore { function_index: 1 }
697                0x02, // S8FromI32
698                0x03, // S8FromI64
699                0x04, // S16FromI32
700                0x05, // S16FromI64
701                0x06, // S32FromI32
702                0x07, // S32FromI64
703                0x08, // S64FromI32
704                0x09, // S64FromI64
705                0x0a, // I32FromS8
706                0x0b, // I32FromS16
707                0x0c, // I32FromS32
708                0x0d, // I32FromS64
709                0x0e, // I64FromS8
710                0x0f, // I64FromS16
711                0x10, // I64FromS32
712                0x11, // I64FromS64
713                0x12, // U8FromI32
714                0x13, // U8FromI64
715                0x14, // U16FromI32
716                0x15, // U16FromI64
717                0x16, // U32FromI32
718                0x17, // U32FromI64
719                0x18, // U64FromI32
720                0x19, // U64FromI64
721                0x1a, // I32FromU8
722                0x1b, // I32FromU16
723                0x1c, // I32FromU32
724                0x1d, // I32FromU64
725                0x1e, // I64FromU8
726                0x1f, // I64FromU16
727                0x20, // I64FromU32
728                0x21, // I64FromU64
729                0x22, // StringLiftMemory
730                0x23, // StringLowerMemory
731                0x24, // StringSize
732                0x025, 0x01, // RecordLift { type_index: 1 }
733                0x026, 0x01, // RecordLower { type_index: 1 }
734            ]
735        );
736    }
737}