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
88
89
use core::convert::TryInto;
use crate::endian::Endian;

/// A data view for reading and writing data in a byte array.
///
/// # Examples
///
/// ```
/// use data_view::View;
/// 
/// let mut buf = [0; 16];
/// 
/// buf.write::<u16>(1, 42);
/// assert_eq!(buf.read::<u16>(1), 42);
/// ```
/// 
/// # Panics
/// Panics if the offset is out of bounds.
pub trait View {
    /// Reads a value of type `E` from the data view. where `E` implements `Endian`.
    /// 
    /// # Examples
    /// 
    /// ```
    /// use data_view::View;
    /// 
    /// let mut buf: [u8; 2] = [42, 0];
    /// 
    /// assert_eq!(buf.read::<u8>(0), 42);
    /// assert_eq!(buf.read::<u8>(1), 0);
    /// ```
    /// 
    /// # Panics
    /// Panics if the offset is out of bounds.
    fn read<E>(&self, offset: usize) -> E
    where
        E: Endian,
        [(); E::NBYTES]:;

    /// Writes a value of type `E` to the data view. where `E` is a type that implements `Endian`.
    /// 
    /// # Examples
    /// 
    /// ```
    /// use data_view::View;
    /// 
    /// let mut buf: [u8; 2] = [0; 2];
    /// 
    /// buf.write::<u8>(0, 42);
    /// assert_eq!(buf, [42, 0]);
    /// ```
    /// 
    /// # Panics
    /// Panics if the offset is out of bounds.
    fn write<E>(&mut self, offset: usize, value: E)
    where
        E: Endian,
        [u8; E::NBYTES]:;
}

impl View for [u8] {
    #[inline(always)]
    fn read<T>(&self, offset: usize) -> T
    where
        T: Endian,
        [u8; T::NBYTES]:,
    {
        #[cfg(not(any(feature = "BE", feature = "NE")))]
        return T::from_bytes_le(self[offset..offset + T::NBYTES].try_into().unwrap());
        #[cfg(feature = "BE")]
        return T::from_bytes_be(self[offset..offset + T::NBYTES].try_into().unwrap());
        #[cfg(feature = "NE")]
        return T::from_bytes_ne(self[offset..offset + T::NBYTES].try_into().unwrap());
    }

    #[inline(always)]
    fn write<T>(&mut self, offset: usize, value: T)
    where
        T: Endian,
        [(); T::NBYTES]:,
    {
        #[cfg(not(any(feature = "BE", feature = "NE")))]
        self[offset..offset + T::NBYTES].copy_from_slice(&value.to_bytes_le());
        #[cfg(feature = "BE")]
        self[offset..offset + T::NBYTES].copy_from_slice(&value.to_bytes_be());
        #[cfg(feature = "NE")]
        self[offset..offset + T::NBYTES].copy_from_slice(&value.to_bytes_ne());
    }
}