1 | use alloc::string::String; |
2 | use core::convert::TryInto; |
3 | use core::fmt; |
4 | use core::marker::PhantomData; |
5 | |
6 | use crate::pod::{from_bytes, slice_from_bytes, Pod}; |
7 | use crate::ReadRef; |
8 | |
9 | /// A newtype for byte slices. |
10 | /// |
11 | /// It has these important features: |
12 | /// - no methods that can panic, such as `Index` |
13 | /// - convenience methods for `Pod` types |
14 | /// - a useful `Debug` implementation |
15 | #[derive (Default, Clone, Copy, PartialEq, Eq)] |
16 | pub struct Bytes<'data>(pub &'data [u8]); |
17 | |
18 | impl<'data> fmt::Debug for Bytes<'data> { |
19 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
20 | debug_list_bytes(self.0, fmt) |
21 | } |
22 | } |
23 | |
24 | impl<'data> Bytes<'data> { |
25 | /// Return the length of the byte slice. |
26 | #[inline ] |
27 | pub fn len(&self) -> usize { |
28 | self.0.len() |
29 | } |
30 | |
31 | /// Return true if the byte slice is empty. |
32 | #[inline ] |
33 | pub fn is_empty(&self) -> bool { |
34 | self.0.is_empty() |
35 | } |
36 | |
37 | /// Skip over the given number of bytes at the start of the byte slice. |
38 | /// |
39 | /// Modifies the byte slice to start after the bytes. |
40 | /// |
41 | /// Returns an error if there are too few bytes. |
42 | #[inline ] |
43 | pub fn skip(&mut self, offset: usize) -> Result<(), ()> { |
44 | match self.0.get(offset..) { |
45 | Some(tail) => { |
46 | self.0 = tail; |
47 | Ok(()) |
48 | } |
49 | None => { |
50 | self.0 = &[]; |
51 | Err(()) |
52 | } |
53 | } |
54 | } |
55 | |
56 | /// Return a reference to the given number of bytes at the start of the byte slice. |
57 | /// |
58 | /// Modifies the byte slice to start after the bytes. |
59 | /// |
60 | /// Returns an error if there are too few bytes. |
61 | #[inline ] |
62 | pub fn read_bytes(&mut self, count: usize) -> Result<Bytes<'data>, ()> { |
63 | match (self.0.get(..count), self.0.get(count..)) { |
64 | (Some(head), Some(tail)) => { |
65 | self.0 = tail; |
66 | Ok(Bytes(head)) |
67 | } |
68 | _ => { |
69 | self.0 = &[]; |
70 | Err(()) |
71 | } |
72 | } |
73 | } |
74 | |
75 | /// Return a reference to the given number of bytes at the given offset of the byte slice. |
76 | /// |
77 | /// Returns an error if the offset is invalid or there are too few bytes. |
78 | #[inline ] |
79 | pub fn read_bytes_at(mut self, offset: usize, count: usize) -> Result<Bytes<'data>, ()> { |
80 | self.skip(offset)?; |
81 | self.read_bytes(count) |
82 | } |
83 | |
84 | /// Return a reference to a `Pod` struct at the start of the byte slice. |
85 | /// |
86 | /// Modifies the byte slice to start after the bytes. |
87 | /// |
88 | /// Returns an error if there are too few bytes or the slice is incorrectly aligned. |
89 | #[inline ] |
90 | pub fn read<T: Pod>(&mut self) -> Result<&'data T, ()> { |
91 | match from_bytes(self.0) { |
92 | Ok((value, tail)) => { |
93 | self.0 = tail; |
94 | Ok(value) |
95 | } |
96 | Err(()) => { |
97 | self.0 = &[]; |
98 | Err(()) |
99 | } |
100 | } |
101 | } |
102 | |
103 | /// Return a reference to a `Pod` struct at the given offset of the byte slice. |
104 | /// |
105 | /// Returns an error if there are too few bytes or the offset is incorrectly aligned. |
106 | #[inline ] |
107 | pub fn read_at<T: Pod>(mut self, offset: usize) -> Result<&'data T, ()> { |
108 | self.skip(offset)?; |
109 | self.read() |
110 | } |
111 | |
112 | /// Return a reference to a slice of `Pod` structs at the start of the byte slice. |
113 | /// |
114 | /// Modifies the byte slice to start after the bytes. |
115 | /// |
116 | /// Returns an error if there are too few bytes or the offset is incorrectly aligned. |
117 | #[inline ] |
118 | pub fn read_slice<T: Pod>(&mut self, count: usize) -> Result<&'data [T], ()> { |
119 | match slice_from_bytes(self.0, count) { |
120 | Ok((value, tail)) => { |
121 | self.0 = tail; |
122 | Ok(value) |
123 | } |
124 | Err(()) => { |
125 | self.0 = &[]; |
126 | Err(()) |
127 | } |
128 | } |
129 | } |
130 | |
131 | /// Return a reference to a slice of `Pod` structs at the given offset of the byte slice. |
132 | /// |
133 | /// Returns an error if there are too few bytes or the offset is incorrectly aligned. |
134 | #[inline ] |
135 | pub fn read_slice_at<T: Pod>(mut self, offset: usize, count: usize) -> Result<&'data [T], ()> { |
136 | self.skip(offset)?; |
137 | self.read_slice(count) |
138 | } |
139 | |
140 | /// Read a null terminated string. |
141 | /// |
142 | /// Does not assume any encoding. |
143 | /// Reads past the null byte, but doesn't return it. |
144 | #[inline ] |
145 | pub fn read_string(&mut self) -> Result<&'data [u8], ()> { |
146 | match memchr::memchr(b' \0' , self.0) { |
147 | Some(null) => { |
148 | // These will never fail. |
149 | let bytes = self.read_bytes(null)?; |
150 | self.skip(1)?; |
151 | Ok(bytes.0) |
152 | } |
153 | None => { |
154 | self.0 = &[]; |
155 | Err(()) |
156 | } |
157 | } |
158 | } |
159 | |
160 | /// Read a null terminated string at an offset. |
161 | /// |
162 | /// Does not assume any encoding. Does not return the null byte. |
163 | #[inline ] |
164 | pub fn read_string_at(mut self, offset: usize) -> Result<&'data [u8], ()> { |
165 | self.skip(offset)?; |
166 | self.read_string() |
167 | } |
168 | |
169 | /// Read an unsigned LEB128 number. |
170 | pub fn read_uleb128(&mut self) -> Result<u64, ()> { |
171 | let mut result = 0; |
172 | let mut shift = 0; |
173 | |
174 | loop { |
175 | let byte = *self.read::<u8>()?; |
176 | if shift == 63 && byte != 0x00 && byte != 0x01 { |
177 | return Err(()); |
178 | } |
179 | result |= u64::from(byte & 0x7f) << shift; |
180 | shift += 7; |
181 | |
182 | if byte & 0x80 == 0 { |
183 | return Ok(result); |
184 | } |
185 | } |
186 | } |
187 | |
188 | /// Read a signed LEB128 number. |
189 | pub fn read_sleb128(&mut self) -> Result<i64, ()> { |
190 | let mut result = 0; |
191 | let mut shift = 0; |
192 | |
193 | loop { |
194 | let byte = *self.read::<u8>()?; |
195 | if shift == 63 && byte != 0x00 && byte != 0x7f { |
196 | return Err(()); |
197 | } |
198 | result |= i64::from(byte & 0x7f) << shift; |
199 | shift += 7; |
200 | |
201 | if byte & 0x80 == 0 { |
202 | if shift < 64 && (byte & 0x40) != 0 { |
203 | // Sign extend the result. |
204 | result |= !0 << shift; |
205 | } |
206 | return Ok(result); |
207 | } |
208 | } |
209 | } |
210 | } |
211 | |
212 | // Only for Debug impl of `Bytes`. |
213 | fn debug_list_bytes(bytes: &[u8], fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
214 | let mut list: DebugList<'_, '_> = fmt.debug_list(); |
215 | list.entries(bytes.iter().take(8).copied().map(DebugByte)); |
216 | if bytes.len() > 8 { |
217 | list.entry(&DebugLen(bytes.len())); |
218 | } |
219 | list.finish() |
220 | } |
221 | |
222 | struct DebugByte(u8); |
223 | |
224 | impl fmt::Debug for DebugByte { |
225 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
226 | write!(fmt, "0x {:02x}" , self.0) |
227 | } |
228 | } |
229 | |
230 | struct DebugLen(usize); |
231 | |
232 | impl fmt::Debug for DebugLen { |
233 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
234 | write!(fmt, "...; {}" , self.0) |
235 | } |
236 | } |
237 | |
238 | /// A newtype for byte strings. |
239 | /// |
240 | /// For byte slices that are strings of an unknown encoding. |
241 | /// |
242 | /// Provides a `Debug` implementation that interprets the bytes as UTF-8. |
243 | #[derive (Default, Clone, Copy, PartialEq, Eq)] |
244 | pub(crate) struct ByteString<'data>(pub &'data [u8]); |
245 | |
246 | impl<'data> fmt::Debug for ByteString<'data> { |
247 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
248 | write!(fmt, " \"{}\"" , String::from_utf8_lossy(self.0)) |
249 | } |
250 | } |
251 | |
252 | #[allow (dead_code)] |
253 | #[inline ] |
254 | pub(crate) fn align(offset: usize, size: usize) -> usize { |
255 | (offset + (size - 1)) & !(size - 1) |
256 | } |
257 | |
258 | #[allow (dead_code)] |
259 | pub(crate) fn data_range( |
260 | data: &[u8], |
261 | data_address: u64, |
262 | range_address: u64, |
263 | size: u64, |
264 | ) -> Option<&[u8]> { |
265 | let offset: u64 = range_address.checked_sub(data_address)?; |
266 | data.get(offset.try_into().ok()?..)? |
267 | .get(..size.try_into().ok()?) |
268 | } |
269 | |
270 | /// A table of zero-terminated strings. |
271 | /// |
272 | /// This is used by most file formats for strings such as section names and symbol names. |
273 | #[derive (Debug, Clone, Copy)] |
274 | pub struct StringTable<'data, R = &'data [u8]> |
275 | where |
276 | R: ReadRef<'data>, |
277 | { |
278 | data: Option<R>, |
279 | start: u64, |
280 | end: u64, |
281 | marker: PhantomData<&'data ()>, |
282 | } |
283 | |
284 | impl<'data, R: ReadRef<'data>> StringTable<'data, R> { |
285 | /// Interpret the given data as a string table. |
286 | pub fn new(data: R, start: u64, end: u64) -> Self { |
287 | StringTable { |
288 | data: Some(data), |
289 | start, |
290 | end, |
291 | marker: PhantomData, |
292 | } |
293 | } |
294 | |
295 | /// Return the string at the given offset. |
296 | pub fn get(&self, offset: u32) -> Result<&'data [u8], ()> { |
297 | match self.data { |
298 | Some(data: R) => { |
299 | let r_start: u64 = self.start.checked_add(offset.into()).ok_or(())?; |
300 | data.read_bytes_at_until(range:r_start..self.end, delimiter:0) |
301 | } |
302 | None => Err(()), |
303 | } |
304 | } |
305 | } |
306 | |
307 | impl<'data, R: ReadRef<'data>> Default for StringTable<'data, R> { |
308 | fn default() -> Self { |
309 | StringTable { |
310 | data: None, |
311 | start: 0, |
312 | end: 0, |
313 | marker: PhantomData, |
314 | } |
315 | } |
316 | } |
317 | |
318 | #[cfg (test)] |
319 | mod tests { |
320 | use super::*; |
321 | use crate::pod::bytes_of; |
322 | |
323 | #[test ] |
324 | fn bytes() { |
325 | let x = u32::to_be(0x0123_4567); |
326 | let data = Bytes(bytes_of(&x)); |
327 | |
328 | let mut bytes = data; |
329 | assert_eq!(bytes.skip(0), Ok(())); |
330 | assert_eq!(bytes, data); |
331 | |
332 | let mut bytes = data; |
333 | assert_eq!(bytes.skip(4), Ok(())); |
334 | assert_eq!(bytes, Bytes(&[])); |
335 | |
336 | let mut bytes = data; |
337 | assert_eq!(bytes.skip(5), Err(())); |
338 | assert_eq!(bytes, Bytes(&[])); |
339 | |
340 | let mut bytes = data; |
341 | assert_eq!(bytes.read_bytes(0), Ok(Bytes(&[]))); |
342 | assert_eq!(bytes, data); |
343 | |
344 | let mut bytes = data; |
345 | assert_eq!(bytes.read_bytes(4), Ok(data)); |
346 | assert_eq!(bytes, Bytes(&[])); |
347 | |
348 | let mut bytes = data; |
349 | assert_eq!(bytes.read_bytes(5), Err(())); |
350 | assert_eq!(bytes, Bytes(&[])); |
351 | |
352 | assert_eq!(data.read_bytes_at(0, 0), Ok(Bytes(&[]))); |
353 | assert_eq!(data.read_bytes_at(4, 0), Ok(Bytes(&[]))); |
354 | assert_eq!(data.read_bytes_at(0, 4), Ok(data)); |
355 | assert_eq!(data.read_bytes_at(1, 4), Err(())); |
356 | |
357 | let mut bytes = data; |
358 | assert_eq!(bytes.read::<u16>(), Ok(&u16::to_be(0x0123))); |
359 | assert_eq!(bytes, Bytes(&[0x45, 0x67])); |
360 | assert_eq!(data.read_at::<u16>(2), Ok(&u16::to_be(0x4567))); |
361 | assert_eq!(data.read_at::<u16>(3), Err(())); |
362 | assert_eq!(data.read_at::<u16>(4), Err(())); |
363 | |
364 | let mut bytes = data; |
365 | assert_eq!(bytes.read::<u32>(), Ok(&x)); |
366 | assert_eq!(bytes, Bytes(&[])); |
367 | |
368 | let mut bytes = data; |
369 | assert_eq!(bytes.read::<u64>(), Err(())); |
370 | assert_eq!(bytes, Bytes(&[])); |
371 | |
372 | let mut bytes = data; |
373 | assert_eq!(bytes.read_slice::<u8>(0), Ok(&[][..])); |
374 | assert_eq!(bytes, data); |
375 | |
376 | let mut bytes = data; |
377 | assert_eq!(bytes.read_slice::<u8>(4), Ok(data.0)); |
378 | assert_eq!(bytes, Bytes(&[])); |
379 | |
380 | let mut bytes = data; |
381 | assert_eq!(bytes.read_slice::<u8>(5), Err(())); |
382 | assert_eq!(bytes, Bytes(&[])); |
383 | |
384 | assert_eq!(data.read_slice_at::<u8>(0, 0), Ok(&[][..])); |
385 | assert_eq!(data.read_slice_at::<u8>(4, 0), Ok(&[][..])); |
386 | assert_eq!(data.read_slice_at::<u8>(0, 4), Ok(data.0)); |
387 | assert_eq!(data.read_slice_at::<u8>(1, 4), Err(())); |
388 | |
389 | let data = Bytes(&[0x01, 0x02, 0x00, 0x04]); |
390 | |
391 | let mut bytes = data; |
392 | assert_eq!(bytes.read_string(), Ok(&data.0[..2])); |
393 | assert_eq!(bytes.0, &data.0[3..]); |
394 | |
395 | let mut bytes = data; |
396 | bytes.skip(3).unwrap(); |
397 | assert_eq!(bytes.read_string(), Err(())); |
398 | assert_eq!(bytes.0, &[]); |
399 | |
400 | assert_eq!(data.read_string_at(0), Ok(&data.0[..2])); |
401 | assert_eq!(data.read_string_at(1), Ok(&data.0[1..2])); |
402 | assert_eq!(data.read_string_at(2), Ok(&[][..])); |
403 | assert_eq!(data.read_string_at(3), Err(())); |
404 | } |
405 | |
406 | #[test ] |
407 | fn bytes_debug() { |
408 | assert_eq!(format!(" {:?}" , Bytes(&[])), "[]" ); |
409 | assert_eq!(format!(" {:?}" , Bytes(&[0x01])), "[0x01]" ); |
410 | assert_eq!( |
411 | format!( |
412 | " {:?}" , |
413 | Bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]) |
414 | ), |
415 | "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]" |
416 | ); |
417 | assert_eq!( |
418 | format!( |
419 | " {:?}" , |
420 | Bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09]) |
421 | ), |
422 | "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, ...; 9]" |
423 | ); |
424 | } |
425 | } |
426 | |