1use crate::{ast::*, interpreter::Instruction, types::*};
4use std::io::{self, Write};
5
6pub trait ToBytes<W>
8where
9 W: Write,
10{
11 fn to_bytes(&self, writer: &mut W) -> io::Result<()>;
13}
14
15impl<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
25impl<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 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
51impl<W> ToBytes<W> for &str
55where
56 W: Write,
57{
58 fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
59 writer.write_all(&[self.len() as u8])?;
61
62 writer.write_all(self.as_bytes())?;
64
65 Ok(())
66 }
67}
68
69impl<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 (self.len() as u64).to_bytes(writer)?;
80
81 for item in self {
83 item.to_bytes(writer)?;
84 }
85
86 Ok(())
87 }
88}
89
90impl<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
119impl<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
129impl<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
142impl<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
158impl<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
183impl<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
199impl<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
214impl<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
229impl<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
244impl<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
281impl<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 #[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, 0x01, 0x61, 0x01, 0x62, 0x01, 0x63, ]
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, 0x0a, ]
461 );
462 assert_to_bytes!(
463 RecordType {
464 fields: vec1![InterfaceType::String, InterfaceType::I32]
465 },
466 &[
467 0x02, 0x0a, 0x0c, ]
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, 0x0a, 0x0e, 0x02, 0x0c, 0x0c, 0x09, ]
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, 0x61, 0x62, 0x63, 0x00, ]
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, 0x02, 0x0c, 0x0d, 0x01, 0x02, ]
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, 0x02, 0x0c, 0x0d, ]
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, 0x61, 0x01, 0x62, 0x00, ]
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, 0x01, 0x00, 0x01, ]
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, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x61, 0x62, 0x01, 0x63, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, 0x01, 0x02, 0x61, 0x62, 0x01, 0x04, 0x01, 0x02, 0x03, ]
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, 0x00, 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x025, 0x01, 0x026, 0x01, ]
735 );
736 }
737}