1use smallvec::{smallvec, SmallVec};
4use wasmparser::{BlockType, ValType};
5
6const ALIGNMENT_MASK: usize = 31;
8
9pub trait Type {
11 fn align(&self) -> usize {
16 (self.size() + ALIGNMENT_MASK) & !ALIGNMENT_MASK
17 }
18
19 fn size(&self) -> usize;
21}
22
23impl Type for &ValType {
24 fn size(&self) -> usize {
25 match self {
26 ValType::I32 | ValType::F32 => 4,
27 ValType::I64 | ValType::F64 => 8,
28 _ => unimplemented!("unknown unsupported type {self}"),
30 }
31 }
32}
33
34impl Type for ValType {
35 fn size(&self) -> usize {
36 (&self).size()
37 }
38}
39
40impl Type for &[ValType] {
41 fn size(&self) -> usize {
42 self.as_ref().iter().map(|t| t.align()).sum::<usize>()
43 }
44}
45
46impl Type for usize {
47 fn align(&self) -> usize {
48 (*self + ALIGNMENT_MASK) & !ALIGNMENT_MASK
49 }
50
51 fn size(&self) -> usize {
52 self.to_le_bytes().len()
53 }
54}
55
56pub trait ToLSBytes {
59 type Output: AsRef<[u8]>;
61
62 fn to_ls_bytes(&self) -> Self::Output;
64}
65
66macro_rules! offset {
67 ($number:ident, $size:expr) => {
68 impl ToLSBytes for $number {
69 type Output = SmallVec<[u8; $size]>;
70
71 fn to_ls_bytes(&self) -> Self::Output {
72 if *self == 0 {
73 return smallvec![0];
74 }
75
76 self.to_le_bytes()
77 .into_iter()
78 .rev()
79 .skip_while(|b| *b == 0)
80 .collect::<Vec<_>>()
81 .into()
82 }
83 }
84 };
85 ($(($number:ident, $size:expr)),+) => {
86 $(offset!($number, $size);)+
87 };
88}
89
90offset! {
91 (usize, 8),
92 (u64, 8),
93 (i64, 8),
94 (i32, 4),
95 (u32, 4),
96 (u16, 2),
97 (u8, 1)
98}
99
100impl ToLSBytes for BlockType {
101 type Output = SmallVec<[u8; 8]>;
102
103 fn to_ls_bytes(&self) -> Self::Output {
104 match self {
105 BlockType::Empty => Default::default(),
106 BlockType::Type(val) => val.size().to_ls_bytes(),
107 BlockType::FuncType(val) => Self::Output::from_slice(&val.to_ls_bytes()),
108 }
109 }
110}
111
112impl ToLSBytes for &ValType {
113 type Output = SmallVec<[u8; 8]>;
114
115 fn to_ls_bytes(&self) -> Self::Output {
116 self.align().to_ls_bytes()
117 }
118}
119
120impl ToLSBytes for &[ValType] {
121 type Output = SmallVec<[u8; 8]>;
122
123 fn to_ls_bytes(&self) -> Self::Output {
124 self.as_ref()
125 .iter()
126 .map(|t| t.align())
127 .sum::<usize>()
128 .to_ls_bytes()
129 }
130}
131
132#[test]
133fn test_usize_to_ls_bytes() {
134 assert_eq!(363usize.to_ls_bytes().to_vec(), vec![0x01, 0x6b]);
135 assert_eq!(255usize.to_ls_bytes().to_vec(), vec![0xff]);
136}