1#[derive(Debug, Clone, Copy)]
4pub struct Cursor<'a> {
5 pub data: &'a [u8],
6 pub pos: usize,
7}
8
9impl<'a> Cursor<'a> {
10 pub fn new(data: &'a [u8]) -> Self {
11 Cursor { data, pos: 0 }
12 }
13
14 pub fn at(data: &'a [u8], pos: usize) -> Self {
15 Cursor { data, pos }
16 }
17
18 pub fn remaining(&self) -> usize {
19 self.data.len().saturating_sub(self.pos)
20 }
21
22 fn take(&mut self, n: usize) -> Option<&'a [u8]> {
23 if self.remaining() < n {
24 return None;
25 }
26 let s = &self.data[self.pos..self.pos + n];
27 self.pos += n;
28 Some(s)
29 }
30
31 pub fn u1(&mut self) -> Option<u8> {
32 self.take(1).map(|s| s[0])
33 }
34
35 pub fn u2(&mut self) -> Option<u16> {
36 self.take(2).map(|s| u16::from_le_bytes([s[0], s[1]]))
37 }
38
39 pub fn u4(&mut self) -> Option<u32> {
40 self.take(4)
41 .map(|s| u32::from_le_bytes([s[0], s[1], s[2], s[3]]))
42 }
43
44 pub fn s4(&mut self) -> Option<i32> {
45 self.u4().map(|v| v as i32)
46 }
47
48 pub fn u8v(&mut self) -> Option<u64> {
49 self.take(8).map(|s| {
50 let mut b = [0u8; 8];
51 b.copy_from_slice(s);
52 u64::from_le_bytes(b)
53 })
54 }
55
56 pub fn peek_rest(&self) -> &'a [u8] {
58 &self.data[self.pos.min(self.data.len())..]
59 }
60
61 pub fn skip(&mut self, n: usize) {
62 self.pos = (self.pos + n).min(self.data.len());
63 }
64
65 pub fn read_uleb128(&mut self) -> Option<u64> {
66 let mut result: u64 = 0;
67 let mut shift = 0u32;
68 loop {
69 let b = self.u1()?;
70 result |= ((b & 0x7f) as u64) << shift;
71 if b & 0x80 == 0 {
72 return Some(result);
73 }
74 shift += 7;
75 if shift > 63 {
76 return None;
77 }
78 }
79 }
80
81 pub fn read_sleb128(&mut self) -> Option<i64> {
82 let mut result: i64 = 0;
83 let mut shift = 0u32;
84 loop {
85 let b = self.u1()?;
86 result |= ((b & 0x7f) as i64) << shift;
87 shift += 7;
88 if b & 0x80 == 0 {
89 if shift < 64 && (b & 0x40) != 0 {
90 result |= -1i64 << shift;
91 }
92 return Some(result);
93 }
94 if shift > 63 {
95 return None;
96 }
97 }
98 }
99
100 pub fn read_uleb128p1(&mut self) -> Option<i64> {
102 self.read_uleb128().map(|v| v as i64 - 1)
103 }
104
105 pub fn read_mutf8(&self, pos: usize, utf16_len: u64) -> Option<String> {
108 if let Some(nul) = self.data[pos..].iter().position(|&b| b == 0) {
113 let ascii = &self.data[pos..pos + nul];
114 if !ascii.is_empty() && ascii.is_ascii() {
115 return Some(unsafe { std::str::from_utf8_unchecked(ascii).to_string() });
117 }
118 }
119 decode_mutf8_units(&self.data[pos..], Some(utf16_len))
120 }
121}
122
123fn decode_mutf8_units(data: &[u8], max_units: Option<u64>) -> Option<String> {
129 let mut out = String::new();
130 let mut i = 0usize;
131 let mut units = 0u64;
132 loop {
133 if let Some(m) = max_units {
134 if units >= m {
135 break;
136 }
137 }
138 if i >= data.len() {
139 return match max_units {
140 Some(_) => None,
141 None => Some(out),
142 };
143 }
144 let b0 = data[i];
145 match b0 {
146 0x00 => break,
147 0x01..=0x7f => {
148 out.push(b0 as char);
149 i += 1;
150 }
151 0xc0..=0xdf => {
152 if i + 1 >= data.len() || (data[i + 1] & 0xc0) != 0x80 {
153 out.push('\u{fffd}');
154 i += 1;
155 } else {
156 let c = (((b0 & 0x1f) as u32) << 6) | ((data[i + 1] & 0x3f) as u32);
157 out.push(char::from_u32(c).unwrap_or('\u{fffd}'));
158 i += 2;
159 }
160 }
161 0xe0..=0xef => {
162 if i + 2 >= data.len()
163 || (data[i + 1] & 0xc0) != 0x80
164 || (data[i + 2] & 0xc0) != 0x80
165 {
166 out.push('\u{fffd}');
167 i += 1;
168 } else {
169 let c = (((b0 & 0x0f) as u32) << 12)
170 | (((data[i + 1] & 0x3f) as u32) << 6)
171 | ((data[i + 2] & 0x3f) as u32);
172 if (0xd800..0xdc00).contains(&c) {
174 if i + 5 < data.len()
175 && (data[i + 3] & 0xf0) == 0xe0
176 && (data[i + 4] & 0xc0) == 0x80
177 && (data[i + 5] & 0xc0) == 0x80
178 {
179 let lo = (((data[i + 3] & 0x0f) as u32) << 12)
180 | (((data[i + 4] & 0x3f) as u32) << 6)
181 | ((data[i + 5] & 0x3f) as u32);
182 let cp = 0x10000 + ((c - 0xd800) << 10) + (lo - 0xdc00);
183 out.push(char::from_u32(cp).unwrap_or('\u{fffd}'));
184 i += 6;
185 units += 2;
186 continue;
187 }
188 out.push('\u{fffd}');
189 i += 3;
190 } else {
191 out.push(char::from_u32(c).unwrap_or('\u{fffd}'));
192 i += 3;
193 }
194 }
195 }
196 _ => {
197 out.push('\u{fffd}');
198 i += 1;
199 }
200 }
201 units += 1;
202 }
203 Some(out)
204}
205
206pub fn mutf8_encode(s: &str) -> Vec<u8> {
212 let mut out = Vec::with_capacity(s.len());
213 for ch in s.chars() {
214 let mut cp = ch as u32;
215 if cp == 0 {
216 out.extend_from_slice(&[0xc0, 0x80]);
217 continue;
218 }
219 if cp > 0xffff {
220 cp -= 0x10000;
222 let hi = 0xd800 + (cp >> 10);
223 let lo = 0xdc00 + (cp & 0x3ff);
224 for unit in [hi, lo] {
225 out.push(0xe0 | ((unit >> 12) as u8));
226 out.push(0x80 | (((unit >> 6) & 0x3f) as u8));
227 out.push(0x80 | ((unit & 0x3f) as u8));
228 }
229 continue;
230 }
231 if cp <= 0x7f {
232 out.push(cp as u8);
233 } else if cp <= 0x7ff {
234 out.push(0xc0 | ((cp >> 6) as u8));
235 out.push(0x80 | ((cp & 0x3f) as u8));
236 } else {
237 out.push(0xe0 | ((cp >> 12) as u8));
238 out.push(0x80 | (((cp >> 6) & 0x3f) as u8));
239 out.push(0x80 | ((cp & 0x3f) as u8));
240 }
241 }
242 out
243}
244
245pub fn mutf8_decode_lossy(data: &[u8]) -> String {
250 decode_mutf8_units(data, None).unwrap_or_default()
251}
252
253pub fn mutf8_decode(data: &[u8], utf16_len: u64) -> Option<String> {
256 Cursor::new(data).read_mutf8(0, utf16_len)
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262
263 #[test]
264 fn uleb() {
265 let mut c = Cursor::new(&[0x00]);
266 assert_eq!(c.read_uleb128(), Some(0));
267 let mut c = Cursor::new(&[0x81, 0x01]);
268 assert_eq!(c.read_uleb128(), Some(129));
269 let mut c = Cursor::new(&[0xff, 0xff, 0xff, 0xff, 0x0f]);
270 assert_eq!(c.read_uleb128(), Some(0xffff_ffff));
271 }
272
273 #[test]
274 fn sleb() {
275 let mut c = Cursor::new(&[0x00]);
276 assert_eq!(c.read_sleb128(), Some(0));
277 let mut c = Cursor::new(&[0x7f]);
278 assert_eq!(c.read_sleb128(), Some(-1));
279 let mut c = Cursor::new(&[0x81, 0x7f]);
280 assert_eq!(c.read_sleb128(), Some(-127));
281 let mut c = Cursor::new(&[0xc0, 0xbb, 0x78]);
282 assert_eq!(c.read_sleb128(), Some(-123456));
283 }
284
285 #[test]
286 fn mutf8_ascii() {
287 assert_eq!(mutf8_decode(b"hello\0", 5).as_deref(), Some("hello"));
288 }
289
290 #[test]
291 fn mutf8_embedded_nul() {
292 assert_eq!(mutf8_decode(&[0xc0, 0x80], 1).as_deref(), Some("\0"));
293 }
294
295 #[test]
296 fn mutf8_supplementary() {
297 let bytes = [0xed, 0xa0, 0xbd, 0xed, 0xb8, 0x80];
299 assert_eq!(mutf8_decode(&bytes, 2).as_deref(), Some("\u{1f600}"));
300 }
301
302 #[test]
303 fn mutf8_encode_roundtrip() {
304 for s in ["hello", "中文", "\u{0}", "\u{1f600}", "a\u{1f600}b"] {
306 let enc = mutf8_encode(s);
307 assert_eq!(mutf8_decode_lossy(&enc), s, "roundtrip {s:?}");
308 }
309 assert_eq!(mutf8_encode("\u{1f600}"), vec![0xed, 0xa0, 0xbd, 0xed, 0xb8, 0x80]);
310 assert_eq!(mutf8_encode("\u{0}"), vec![0xc0, 0x80]);
311 }
312
313 #[test]
314 fn mutf8_lossy_delimited() {
315 let bytes = [0xed, 0xa0, 0xbd, 0xed, 0xb8, 0x80, 0x00, 0x41];
317 assert_eq!(mutf8_decode_lossy(&bytes), "\u{1f600}");
318 assert_eq!(mutf8_decode_lossy(&[0xc0, 0x80]), "\u{0}");
320 assert_eq!(
322 mutf8_decode_lossy(&[0xed, 0xa0, 0xbd, 0x41]),
323 "\u{fffd}A"
324 );
325 }
326}