Skip to main content

object/read/
util.rs

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