//! Working with byte slices that have an associated endianity.
#[cfg(feature = "read")] use alloc::borrow::Cow; #[cfg(feature = "read")] use alloc::string::String; use core::fmt; use core::ops::{Deref, Range, RangeFrom, RangeTo}; use core::str;
/// A `&[u8]` slice with endianity metadata. /// /// This implements the `Reader` trait, which is used for all reading of DWARF sections. #[derive(Default, Clone, Copy, PartialEq, Eq, Hash)] pubstruct EndianSlice<'input, Endian> where
Endian: Endianity,
{
slice: &'input [u8],
endian: Endian,
}
impl<'input, Endian> EndianSlice<'input, Endian> where
Endian: Endianity,
{ /// Construct a new `EndianSlice` with the given slice and endianity. #[inline] pubfn new(slice: &'input [u8], endian: Endian) -> EndianSlice<'input, Endian> {
EndianSlice { slice, endian }
}
/// Return a reference to the raw slice. #[inline] #[doc(hidden)] #[deprecated(note = "Method renamed to EndianSlice::slice; use that instead.")] pubfn buf(&self) -> &'input [u8] { self.slice
}
/// Return a reference to the raw slice. #[inline] pubfn slice(&self) -> &'input [u8] { self.slice
}
/// Split the slice in two at the given index, resulting in the tuple where /// the first item has range [0, idx), and the second has range [idx, /// len). Panics if the index is out of bounds. #[inline] pubfn split_at(
&self,
idx: usize,
) -> (EndianSlice<'input, Endian>, EndianSlice<'input, Endian>) {
(self.range_to(..idx), self.range_from(idx..))
}
/// Find the first occurrence of a byte in the slice, and return its index. #[inline] pubfn find(&self, byte: u8) -> Option<usize> { self.slice.iter().position(|ch| *ch == byte)
}
/// Return the offset of the start of the slice relative to the start /// of the given slice. #[inline] pubfn offset_from(&self, base: EndianSlice<'input, Endian>) -> usize { let base_ptr = base.slice.as_ptr() as usize; let ptr = self.slice.as_ptr() as usize;
debug_assert!(base_ptr <= ptr);
debug_assert!(ptr + self.slice.len() <= base_ptr + base.slice.len());
ptr - base_ptr
}
/// Converts the slice to a string using `str::from_utf8`. /// /// Returns an error if the slice contains invalid characters. #[inline] pubfn to_string(&self) -> Result<&'input str> {
str::from_utf8(self.slice).map_err(|_| Error::BadUtf8)
}
/// Converts the slice to a string, including invalid characters, /// using `String::from_utf8_lossy`. #[cfg(feature = "read")] #[inline] pubfn to_string_lossy(&self) -> Cow<'input, str> {
String::from_utf8_lossy(self.slice)
}
#[inline] fn read_slice(&mutself, len: usize) -> Result<&'input [u8]> { ifself.slice.len() < len {
Err(Error::UnexpectedEof(self.offset_id()))
} else { let val = &self.slice[..len]; self.slice = &self.slice[len..];
Ok(val)
}
}
}
/// # Range Methods /// /// Unfortunately, `std::ops::Index` *must* return a reference, so we can't /// implement `Index<Range<usize>>` to return a new `EndianSlice` the way we would /// like to. Instead, we abandon fancy indexing operators and have these plain /// old methods. impl<'input, Endian> EndianSlice<'input, Endian> where
Endian: Endianity,
{ /// Take the given `start..end` range of the underlying slice and return a /// new `EndianSlice`. /// /// ``` /// use gimli::{EndianSlice, LittleEndian}; /// /// let slice = &[0x01, 0x02, 0x03, 0x04]; /// let endian_slice = EndianSlice::new(slice, LittleEndian); /// assert_eq!(endian_slice.range(1..3), /// EndianSlice::new(&slice[1..3], LittleEndian)); /// ``` pubfn range(&self, idx: Range<usize>) -> EndianSlice<'input, Endian> {
EndianSlice {
slice: &self.slice[idx],
endian: self.endian,
}
}
/// Take the given `start..` range of the underlying slice and return a new /// `EndianSlice`. /// /// ``` /// use gimli::{EndianSlice, LittleEndian}; /// /// let slice = &[0x01, 0x02, 0x03, 0x04]; /// let endian_slice = EndianSlice::new(slice, LittleEndian); /// assert_eq!(endian_slice.range_from(2..), /// EndianSlice::new(&slice[2..], LittleEndian)); /// ``` pubfn range_from(&self, idx: RangeFrom<usize>) -> EndianSlice<'input, Endian> {
EndianSlice {
slice: &self.slice[idx],
endian: self.endian,
}
}
/// Take the given `..end` range of the underlying slice and return a new /// `EndianSlice`. /// /// ``` /// use gimli::{EndianSlice, LittleEndian}; /// /// let slice = &[0x01, 0x02, 0x03, 0x04]; /// let endian_slice = EndianSlice::new(slice, LittleEndian); /// assert_eq!(endian_slice.range_to(..3), /// EndianSlice::new(&slice[..3], LittleEndian)); /// ``` pubfn range_to(&self, idx: RangeTo<usize>) -> EndianSlice<'input, Endian> {
EndianSlice {
slice: &self.slice[idx],
endian: self.endian,
}
}
}
impl<'input, Endian> Deref for EndianSlice<'input, Endian> where
Endian: Endianity,
{ type Target = [u8]; fn deref(&self) -> &Self::Target { self.slice
}
}
#[inline] fn offset_id(&self) -> ReaderOffsetId {
ReaderOffsetId(self.slice.as_ptr() as u64)
}
#[inline] fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset> { let id = id.0; let self_id = self.slice.as_ptr() as u64; let self_len = self.slice.len() as u64; if id >= self_id && id <= self_id + self_len {
Some((id - self_id) as usize)
} else {
None
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.