/// A newtype for byte slices. /// /// It has these important features: /// - no methods that can panic, such as `Index` /// - convenience methods for `Pod` types /// - a useful `Debug` implementation #[derive(Default, Clone, Copy, PartialEq, Eq)] pubstruct Bytes<'data>(pub &'data [u8]);
impl<'data> Bytes<'data> { /// Return the length of the byte slice. #[inline] pubfn len(&self) -> usize { self.0.len()
}
/// Return true if the byte slice is empty. #[inline] pubfn is_empty(&self) -> bool { self.0.is_empty()
}
/// Skip over the given number of bytes at the start of the byte slice. /// /// Modifies the byte slice to start after the bytes. /// /// Returns an error if there are too few bytes. #[inline] pubfn skip(&mutself, offset: usize) -> Result<(), ()> { matchself.0.get(offset..) {
Some(tail) => { self.0 = tail;
Ok(())
}
None => { self.0 = &[];
Err(())
}
}
}
/// Return a reference to the given number of bytes at the start of the byte slice. /// /// Modifies the byte slice to start after the bytes. /// /// Returns an error if there are too few bytes. #[inline] pubfn read_bytes(&mutself, count: usize) -> Result<Bytes<'data>, ()> { match (self.0.get(..count), self.0.get(count..)) {
(Some(head), Some(tail)) => { self.0 = tail;
Ok(Bytes(head))
}
_ => { self.0 = &[];
Err(())
}
}
}
/// Return a reference to the given number of bytes at the given offset of the byte slice. /// /// Returns an error if the offset is invalid or there are too few bytes. #[inline] pubfn read_bytes_at(mutself, offset: usize, count: usize) -> Result<Bytes<'data>, ()> { self.skip(offset)?; self.read_bytes(count)
}
/// Return a reference to a `Pod` struct at the start of the byte slice. /// /// Modifies the byte slice to start after the bytes. /// /// Returns an error if there are too few bytes or the slice is incorrectly aligned. #[inline] pubfn read<T: Pod>(&mutself) -> Result<&'data T, ()> { match from_bytes(self.0) {
Ok((value, tail)) => { self.0 = tail;
Ok(value)
}
Err(()) => { self.0 = &[];
Err(())
}
}
}
/// Return a reference to a `Pod` struct at the given offset of the byte slice. /// /// Returns an error if there are too few bytes or the offset is incorrectly aligned. #[inline] pubfn read_at<T: Pod>(mutself, offset: usize) -> Result<&'data T, ()> { self.skip(offset)?; self.read()
}
/// Return a reference to a slice of `Pod` structs at the start of the byte slice. /// /// Modifies the byte slice to start after the bytes. /// /// Returns an error if there are too few bytes or the offset is incorrectly aligned. #[inline] pubfn read_slice<T: Pod>(&mutself, count: usize) -> Result<&e='color:blue'>'data [T], ()> { match slice_from_bytes(self.0, count) {
Ok((value, tail)) => { self.0 = tail;
Ok(value)
}
Err(()) => { self.0 = &[];
Err(())
}
}
}
/// Return a reference to a slice of `Pod` structs at the given offset of the byte slice. /// /// Returns an error if there are too few bytes or the offset is incorrectly aligned. #[inline] pubfn read_slice_at<T: Pod>(mutself, offset: usize, count: usize) -> Result<&'data [T], ()> { self.skip(offset)?; self.read_slice(count)
}
/// Read a null terminated string. /// /// Does not assume any encoding. /// Reads past the null byte, but doesn't return it. #[inline] pubfn read_string(&mutself) -> Result<&'data [u8], ()> { match memchr::memchr(b'\0', self.0) {
Some(null) => { // These will never fail. let bytes = self.read_bytes(null)?; self.skip(1)?;
Ok(bytes.0)
}
None => { self.0 = &[];
Err(())
}
}
}
/// Read a null terminated string at an offset. /// /// Does not assume any encoding. Does not return the null byte. #[inline] pubfn read_string_at(mutself, offset: usize) -> Result<&'data [u8], ()> { self.skip(offset)?; self.read_string()
}
/// Read an unsigned LEB128 number. pubfn read_uleb128(&mutself) -> Result<u64, ()> { letmut result = 0; letmut shift = 0;
/// A newtype for byte strings. /// /// For byte slices that are strings of an unknown encoding. /// /// Provides a `Debug` implementation that interprets the bytes as UTF-8. #[derive(Default, Clone, Copy, PartialEq, Eq)] pub(crate) struct ByteString<'data>(pub &'data [u8]);
/// A table of zero-terminated strings. /// /// This is used by most file formats for strings such as section names and symbol names. #[derive(Debug, Clone, Copy)] pubstruct StringTable<'data, R = &'data [u8]> where
R: ReadRef<'data>,
{
data: Option<R>,
start: u64,
end: u64,
marker: PhantomData<&'data ()>,
}
impl<'data, R: ReadRef<'data>> StringTable<'data, R> { /// Interpret the given data as a string table. pubfn new(data: R, start: u64, end: u64) -> Self {
StringTable {
data: Some(data),
start,
end,
marker: PhantomData,
}
}
/// Return the string at the given offset. pubfn get(&self, offset: u32) -> Result<&'data [u8], ()> { matchself.data {
Some(data) => { let r_start = self.start.checked_add(offset.into()).ok_or(())?;
data.read_bytes_at_until(r_start..self.end, 0)
}
None => Err(()),
}
}
}
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.