1pub fn encode_name(name: &[u8]) -> Vec<u8> {
7 let mut encoded_name: Vec<u8> = Vec::new();
8 let mut segments: Vec<[u8; 4]> = Vec::new();
9 let mut i = 0;
10 if name[0] == b'\\' {
11 encoded_name.push(b'\\');
12 i = 1;
13 }
14 loop {
15 if i == name.len() {
16 break;
17 }
18
19 if name[i] == b'^' {
20 assert!(
21 (encoded_name.is_empty() || encoded_name[encoded_name.len() - 1] == b'^')
22 && segments.is_empty()
23 );
24 encoded_name.push(b'^');
25 i += 1;
26 continue;
27 }
28
29 assert!((name[i] == b'_') || (name[i] >= b'A' && name[i] <= b'Z'));
30 let mut seg: [u8; 4] = [b'_'; 4];
31 let mut seg_i = 0;
32 loop {
33 let off = i + seg_i;
34 if off == name.len() || name[off] == b'.' {
35 break;
36 }
37
38 assert!(seg_i < 4);
39 assert!(
40 (name[off] == b'_')
41 || (name[off] >= b'A' && name[off] <= b'Z')
42 || (name[off] >= b'0' && name[off] <= b'9')
43 );
44 seg[seg_i] = name[off];
45 seg_i += 1
46 }
47 assert!(seg_i > 0);
48 segments.push(seg);
49 i += seg_i;
51 if i < name.len() {
52 i += 1;
54 }
55 }
56 if segments.len() > 2 {
57 encoded_name.push(0x2f);
58 encoded_name.push(u8::try_from(segments.len()).unwrap());
59 } else if segments.len() > 1 {
60 encoded_name.push(0x2e);
61 }
62 for seg in segments {
63 encoded_name.extend_from_slice(&seg);
64 }
65 encoded_name
66}
67
68pub fn encode_package_len(len: usize) -> Vec<u8> {
69 assert!(len < (1 << 28) - 1);
70 let mut result: Vec<u8> = Vec::new();
71 if len < 63 {
72 result.push(u8::try_from(len).unwrap() + 1);
73 } else {
74 let len_bytes = if len < 1 << 12 {
78 2
79 } else if len < 1 << 20 {
80 3
81 } else {
82 4
83 };
84
85 let mut encoded_len: [u8; 4] = [0; 4];
86 let mut rem = len + len_bytes;
87 encoded_len[0] =
89 u8::try_from((len_bytes - 1) << 6).unwrap() | u8::try_from(rem & 0xf).unwrap();
90 rem >>= 4;
91 for e in encoded_len.iter_mut().take(len_bytes).skip(1) {
92 *e = u8::try_from(rem & 0xff).unwrap();
93 rem >>= 8;
94 }
95
96 result.extend_from_slice(&encoded_len[..len_bytes]);
97 }
98 result
99}
100
101pub fn encode_integer(value: u64) -> Vec<u8> {
102 let mut byte_stream: Vec<u8> = Vec::new();
103 let end;
104 if value == 0 {
105 return vec![0];
107 } else if value == 1 {
108 return vec![1];
110 } else if value <= 0xff {
111 byte_stream.push(0xa);
112 end = 1;
113 } else if value <= 0xffff {
114 byte_stream.push(0xb);
115 end = 2;
116 } else if value <= 0xffffffff {
117 byte_stream.push(0xc);
118 end = 4;
119 } else {
120 byte_stream.push(0xe);
121 end = 8;
122 }
123
124 let bytes = value.to_le_bytes();
125 byte_stream.extend_from_slice(&bytes[..end]);
126 byte_stream
127}
128
129pub fn encode_dword(value: u32) -> Vec<u8> {
130 let mut byte_stream = vec![0xcu8];
131 byte_stream.extend_from_slice(&value.to_le_bytes());
132 while byte_stream.len() < 5 {
133 byte_stream.push(0);
134 }
135 byte_stream
136}
137
138pub fn encode_string(value: &[u8]) -> Vec<u8> {
139 let mut byte_stream: Vec<u8> = Vec::new();
140 byte_stream.push(0xd);
141 byte_stream.extend_from_slice(value);
142 byte_stream.push(0);
143 byte_stream
144}
145
146pub fn char_to_hex(value: u8) -> u8 {
147 match value {
148 b'0'..=b'9' => value - b'0',
149 b'a'..=b'f' => 10 + value - b'a',
150 b'A'..=b'F' => 10 + value - b'A',
151 _ => panic!("Unsupported hex char {}", value),
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158 use crate::aml::test_helpers::verify_expected_bytes;
159
160 #[test]
161 fn verify_simple_name() {
162 let bytes = encode_name(b"FOO");
163 verify_expected_bytes(&bytes, b"FOO_");
164 }
165
166 #[test]
167 fn verify_simple_name_with_root() {
168 let bytes = encode_name(b"\\FOO");
169 verify_expected_bytes(&bytes, b"\\FOO_");
170 }
171
172 #[test]
173 fn verify_simple_name_with_prefix() {
174 let bytes = encode_name(b"^FOO");
175 verify_expected_bytes(&bytes, b"^FOO_");
176 }
177
178 #[test]
179 fn verify_dual_name() {
180 let bytes = encode_name(b"FOO.BAR");
181 verify_expected_bytes(&bytes, b"\x2eFOO_BAR_");
182 }
183
184 #[test]
185 fn verify_dual_name_with_root() {
186 let bytes = encode_name(b"\\_SB.FOO");
187 verify_expected_bytes(&bytes, b"\\\x2e_SB_FOO_");
188 }
189
190 #[test]
191 fn verify_multi_name() {
192 let bytes = encode_name(b"FOO.BAR.BAZ.BLAM");
193 verify_expected_bytes(&bytes, b"\x2f\x04FOO_BAR_BAZ_BLAM");
194 }
195}