web_assembler/
util.rs

1#[inline]
2pub fn write_uint8(buf: &mut Vec<u8>, u: u8) -> usize {
3    buf.push(u);
4    1
5}
6
7#[inline]
8pub fn write_uint16(buf: &mut Vec<u8>, u: u16) -> usize {
9    let mut size = 0;
10    size += write_uint8(buf, (u & 0xff) as u8);
11    size += write_uint8(buf, ((u >> 8) & 0xff) as u8);
12    size
13}
14
15#[inline]
16pub fn write_uint32(buf: &mut Vec<u8>, u: u32) -> usize {
17    let mut size = 0;
18    size += write_uint16(buf, (u & 0xffff) as u16);
19    size += write_uint16(buf, ((u >> 16) & 0xffff) as u16);
20    size
21}
22
23#[inline]
24pub fn write_uint64(buf: &mut Vec<u8>, u: u64) -> usize {
25    let mut size = 0;
26    size += write_uint32(buf, (u & 0xffffffff) as u32);
27    size += write_uint32(buf, ((u >> 32) & 0xffffffff) as u32);
28    size
29}
30
31#[inline]
32pub fn write_varuint1(buf: &mut Vec<u8>, u: u8) -> usize {
33    write_uint8(buf, u)
34}
35
36#[allow(dead_code)]
37#[inline]
38pub fn write_varuint7(buf: &mut Vec<u8>, u: u8) -> usize {
39    write_uint8(buf, u)
40}
41
42#[inline]
43pub fn write_varint7(buf: &mut Vec<u8>, i: i8) -> usize {
44    write_uint8(buf, (i as u8) ^ 0x80)
45}
46
47macro_rules! gen_write_var_unsigned {
48    ($name: ident, $ty: ty) => {
49        #[inline]
50        #[allow(unused_comparisons)]
51        #[allow(overflowing_literals)]
52        pub fn $name(buf: &mut Vec<u8>, mut u: $ty) -> usize {
53            let end: i8 = if u < 0 { 0xff } else { 0 };
54
55            let mut size = 0;
56            let bit7 = 0b01111111;
57            let mut cur: u8 = (u & bit7) as u8;
58            // rust generates sar for i32 by >>
59            u >>= 7;
60            while u != (end as $ty) {
61                size += write_uint8(buf, cur | 0x80);
62                cur = (u & bit7) as u8;
63                u >>= 7;
64            }
65            size += write_uint8(buf, cur);
66            size
67        }
68    };
69}
70
71macro_rules! gen_write_var_signed {
72    ($name: ident, $ty: ty) => {
73        #[inline]
74        pub fn $name(buf: &mut Vec<u8>, mut u: $ty) -> usize {
75            let mut size = 0;
76            let bit7 = 0b0111_1111;
77            let mut cur: u8 = (u & bit7) as u8;
78            let upper = 64 as $ty;
79            let lower = -64 as $ty;
80            while u < lower || upper <= u {
81                size += write_uint8(buf, cur | 0x80);
82                u >>= 7;
83                cur = (u & bit7) as u8;
84            }
85            size += write_uint8(buf, cur);
86            size
87        }
88    };
89}
90
91gen_write_var_unsigned!(write_varuint32, u32);
92gen_write_var_signed!(write_varint32, i32);
93gen_write_var_signed!(write_varint64, i64);
94
95#[cfg(test)]
96mod test {
97    use super::*;
98
99    #[test]
100    fn test_write_varint32() {
101        let mut buf = vec![];
102        let size = write_varint32(&mut buf, 0b0110_0001);
103        assert_eq!(size, 2);
104        assert_eq!(buf, &[0b1110_0001, 0b0000_0000]);
105    }
106
107    #[test]
108    fn test_write_varint32_edge1() {
109        let mut buf = vec![];
110        let size = write_varint32(&mut buf, 63);
111        assert_eq!(size, 1);
112        assert_eq!(buf, &[0b0011_1111]);
113    }
114
115    #[test]
116    fn test_write_varint32_edge2() {
117        let mut buf = vec![];
118        let size = write_varint32(&mut buf, 64);
119        assert_eq!(size, 2);
120        assert_eq!(buf, &[0b1100_0000, 0b0000_0000]);
121    }
122
123    #[test]
124    fn test_write_varint32_edge3() {
125        let mut buf = vec![];
126        let size = write_varint32(&mut buf, -64);
127        assert_eq!(size, 1);
128        assert_eq!(buf, &[0b0100_0000]);
129    }
130
131    #[test]
132    fn test_write_varint32_edge4() {
133        let mut buf = vec![];
134        let size = write_varint32(&mut buf, -65);
135        assert_eq!(size, 2);
136        assert_eq!(buf, &[0b1011_1111, 0b0111_1111]);
137    }
138}
139
140#[inline]
141pub fn write_slice(buf: &mut Vec<u8>, u: &[u8]) -> usize {
142    buf.extend_from_slice(u);
143    u.len()
144}