1use crate::error::EncodeError;
2use crate::value::Value;
3
4pub fn encode_uleb128(mut value: u64, out: &mut Vec<u8>) {
5 loop {
6 let mut byte = (value & 0x7F) as u8;
7 value >>= 7;
8 if value != 0 {
9 byte |= 0x80;
10 }
11 out.push(byte);
12 if value == 0 {
13 break;
14 }
15 }
16}
17
18pub fn encode_sleb128(mut value: i64, out: &mut Vec<u8>) {
19 loop {
20 let byte = (value & 0x7F) as u8;
21 let sign_bit = byte & 0x40;
22 value >>= 7;
23
24 let done = (value == 0 && sign_bit == 0) || (value == -1 && sign_bit != 0);
25
26 out.push(if done { byte } else { byte | 0x80 });
27
28 if done {
29 break;
30 }
31 }
32}
33
34pub fn encode(value: &Value) -> Result<Vec<u8>, EncodeError> {
35 let mut out = Vec::new();
36 encode_into(value, &mut out)?;
37 Ok(out)
38}
39
40fn encode_into(value: &Value, out: &mut Vec<u8>) -> Result<(), EncodeError> {
41 match value {
42 Value::Null => {
43 out.push(0x00);
44 }
45
46 Value::Bool(false) => {
47 out.push(0x01);
48 }
49
50 Value::Bool(true) => {
51 out.push(0x02);
52 }
53
54 Value::Int(number) => {
55 out.push(0x10);
56 encode_sleb128(*number, out);
57 }
58
59 Value::String(string) => {
60 out.push(0x20);
61
62 if !string.is_char_boundary(string.len()) {
63 return Err(EncodeError::InvalidUtf8);
64 }
65
66 let bytes = string.as_bytes();
67 encode_uleb128(bytes.len() as u64, out);
68 out.extend_from_slice(bytes);
69 }
70
71 Value::Bytes(bytes) => {
72 out.push(0x21);
73 encode_uleb128(bytes.len() as u64, out);
74 out.extend_from_slice(bytes);
75 }
76
77 Value::List(items) => {
78 out.push(0x30);
79 encode_uleb128(items.len() as u64, out);
80 for item in items {
81 encode_into(item, out)?;
82 }
83 }
84
85 Value::Map(map) => {
86 out.push(0x40);
87 encode_uleb128(map.len() as u64, out);
88
89 for (key, value) in map {
91 out.push(0x20);
93
94 if !key.is_char_boundary(key.len()) {
95 return Err(EncodeError::InvalidUtf8);
96 }
97
98 let key_bytes = key.as_bytes();
99 encode_uleb128(key_bytes.len() as u64, out);
100 out.extend_from_slice(key_bytes);
101
102 encode_into(value, out)?;
103 }
104 }
105 }
106
107 Ok(())
108}