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;
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)]
16pub struct Bytes<'data>(pub &'data [u8]);
17
18impl<'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
24impl<'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`.
213fn debug_list_bytes(bytes: &[u8], fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
214    let mut list = 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
222struct DebugByte(u8);
223
224impl fmt::Debug for DebugByte {
225    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
226        write!(fmt, "0x{:02x}", self.0)
227    }
228}
229
230struct DebugLen(usize);
231
232impl 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)]
244pub(crate) struct ByteString<'data>(pub &'data [u8]);
245
246impl<'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]
254pub(crate) fn align(offset: usize, size: usize) -> usize {
255    (offset + (size - 1)) & !(size - 1)
256}
257
258#[allow(dead_code)]
259pub(crate) fn data_range(
260    data: &[u8],
261    data_address: u64,
262    range_address: u64,
263    size: u64,
264) -> Option<&[u8]> {
265    let offset = 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)]
274pub struct StringTable<'data, R = &'data [u8]>
275where
276    R: ReadRef<'data>,
277{
278    data: Option<R>,
279    start: u64,
280    end: u64,
281    marker: PhantomData<&'data ()>,
282}
283
284impl<'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) => {
299                let r_start = self.start.checked_add(offset.into()).ok_or(())?;
300                data.read_bytes_at_until(r_start..self.end, 0)
301            }
302            None => Err(()),
303        }
304    }
305}
306
307impl<'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)]
319mod 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}