1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
use crate::endian::*;
/// A data view for reading and writing data in byte array.
///
/// # Examples
///
/// ```
/// use data_view::View;
///
/// let mut buf = [0; 16];
///
/// buf.write_at(1, 42_u16);
/// assert_eq!(buf.read_at::<u16>(1).unwrap(), 42);
/// ```
pub trait View {
/// Reads a value of type `E: Endian` from view.
///
/// # Examples
///
/// ```
/// use data_view::View;
///
/// let mut buf: [u8; 2] = [12, 34];
///
/// assert_eq!(buf.read_at::<u8>(0).unwrap(), 12);
/// assert_eq!(buf.read_at::<u8>(1).unwrap(), 34);
/// ```
fn read_at<E: Endian>(&self, offset: usize) -> Option<E>;
/// Reads a value of type `E: Endian` from view, without doing bounds checking.
/// For a safe alternative see [`read_at`].
///
/// [`read_at`]: #method.read_at
///
/// # Examples
///
/// ```
/// use data_view::View;
///
/// let mut buf: [u8; 2] = [12, 34];
/// unsafe {
/// assert_eq!(buf.read_at_unchecked::<u8>(0), 12);
/// assert_eq!(buf.read_at_unchecked::<u8>(1), 34);
/// }
/// ```
/// # Safety
///
/// Calling this method with an out-of-bounds index is *[undefined behavior]*
unsafe fn read_at_unchecked<E: Endian>(&self, offset: usize) -> E;
/// Writes a value of type `E: Endian` to data view.
///
/// # Examples
///
/// ```
/// use data_view::View;
///
/// let mut buf: [u8; 2] = [0; 2];
///
/// buf.write_at(0, 12_u8);
/// buf.write_at(1, 34_u8);
/// assert_eq!(buf, [12, 34]);
/// ```
///
/// # Panics
/// Panics if the offset is out of bounds.
fn write_at<E: Endian>(&mut self, offset: usize, num: E);
}
impl View for [u8] {
#[inline]
fn read_at<E: Endian>(&self, offset: usize) -> Option<E> {
let bytes = self.get(offset..offset + E::SIZE)?;
Some(unsafe { num_from(bytes) })
}
#[inline]
unsafe fn read_at_unchecked<E: Endian>(&self, offset: usize) -> E {
let total_len = offset + E::SIZE;
debug_assert!(total_len <= self.len());
num_from(self.get_unchecked(offset..total_len))
}
#[inline]
fn write_at<E: Endian>(&mut self, offset: usize, num: E) {
assert!(offset + E::SIZE <= self.len());
unsafe { num_write_at(num, self.as_mut_ptr().add(offset)) };
}
}