data_view/dataview.rs
1use super::*;
2
3/// This struct represents a data view for reading and writing data in a byte array.
4/// When read/write, This increment current offset by the size of the value.
5#[derive(Debug, Clone, PartialEq, Eq, Default)]
6pub struct DataView<T> {
7 pub data: T,
8 pub offset: usize,
9}
10
11impl<T> DataView<T> {
12 /// # Examples
13 ///
14 /// ```
15 /// use data_view::DataView;
16 ///
17 /// let view = DataView::new([0; 16]);
18 /// ```
19 pub const fn new(data: T) -> Self {
20 Self { data, offset: 0 }
21 }
22}
23
24impl<T: AsRef<[u8]>> DataView<T> {
25 /// Returns remaining slice from the current offset.
26 /// It doesn't change the offset.
27 ///
28 /// # Examples
29 ///
30 /// ```
31 /// use data_view::DataView;
32 ///
33 /// let mut view = DataView::new([1, 2]);
34 ///
35 /// assert_eq!(view.remaining_slice(), &[1, 2]);
36 /// view.offset = 42;
37 /// assert!(view.remaining_slice().is_empty());
38 /// ```
39 #[inline]
40 pub fn remaining_slice(&self) -> &[u8] {
41 let data = self.data.as_ref();
42 unsafe { data.get_unchecked(self.offset.min(data.len())..) }
43 }
44
45 /// Reads a value of type `E: Endian` from the DataView.
46 ///
47 /// # Examples
48 ///
49 /// ```
50 /// use data_view::DataView;
51 ///
52 /// let mut view = DataView::new([0; 4]);
53 ///
54 /// view.write::<u16>(42);
55 /// view.offset = 0;
56 /// assert_eq!(view.read::<u16>(), Some(42));
57 /// assert_eq!(view.read::<u32>(), None);
58 /// ```
59 #[inline]
60 pub fn read<E: Endian>(&mut self) -> Option<E> {
61 let data = self.data.as_ref();
62 let total_len = self.offset + size_of::<E>();
63 if total_len > data.len() {
64 return None;
65 }
66 let num = unsafe { E::__read_at__(data.as_ptr().add(self.offset)) };
67 self.offset = total_len;
68 Some(num)
69 }
70
71 /// Read slice from the current offset.
72 ///
73 /// # Example
74 /// ```
75 /// use data_view::DataView;
76 ///
77 /// let mut view = DataView::new([1, 2, 3]);
78 ///
79 /// assert_eq!(view.read_slice(2), Some([1, 2].as_ref()));
80 /// assert_eq!(view.read_slice(3), None);
81 /// ```
82 #[inline]
83 pub fn read_slice(&mut self, len: usize) -> Option<&[u8]> {
84 let total_len = self.offset + len;
85 let slice = self.data.as_ref().get(self.offset..total_len)?;
86 self.offset = total_len;
87 Some(slice)
88 }
89
90 /// Create a buffer and returns it, from the current offset.
91 ///
92 /// # Examples
93 ///
94 /// ```
95 /// use data_view::DataView;
96 ///
97 /// let mut view = DataView::new([1, 2, 3]);
98 ///
99 /// assert_eq!(view.read_buf(), Some([1, 2]));
100 /// assert_eq!(view.read_buf::<3>(), None);
101 /// ```
102 #[inline]
103 pub fn read_buf<const N: usize>(&mut self) -> Option<[u8; N]> {
104 let data = self.data.as_ref();
105 let total_len = self.offset + N;
106 if total_len > data.len() {
107 return None;
108 }
109 let buf = unsafe { ptr::read(data.as_ptr().add(self.offset) as *const [u8; N]) };
110 self.offset = total_len;
111 Some(buf)
112 }
113}
114
115impl<T: AsMut<[u8]>> DataView<T> {
116 /// # Examples
117 ///
118 /// ```
119 /// use data_view::DataView;
120 ///
121 /// let mut view = DataView::new([0; 3]);
122 ///
123 /// assert_eq!(view.write(42_u16), Ok(()));
124 /// assert_eq!(view.write(123_u32), Err(()));
125 /// ```
126 #[inline]
127 pub fn write<E: Endian>(&mut self, num: E) -> Result<(), ()> {
128 let data = self.data.as_mut();
129 let total_len = self.offset + size_of::<E>();
130 if total_len > data.len() {
131 return Err(());
132 }
133 unsafe { E::__write_at__(num, data.as_mut_ptr().add(self.offset)) };
134 self.offset = total_len;
135 Ok(())
136 }
137
138 /// Writes a slice into the data view.
139 ///
140 /// # Examples
141 ///
142 /// ```
143 /// use data_view::DataView;
144 ///
145 /// let mut view = DataView::new([0; 3]);
146 ///
147 /// assert_eq!(view.write_slice([4, 2]), Ok(()));
148 /// assert_eq!(view.write_slice([1, 2, 3]), Err(()));
149 /// assert_eq!(view.data, [4, 2, 0]);
150 /// ```
151 #[inline]
152 pub fn write_slice(&mut self, slice: impl AsRef<[u8]>) -> Result<(), ()> {
153 let src = slice.as_ref();
154 let data = self.data.as_mut();
155 let count = src.len();
156 let total_len = self.offset + count;
157 if total_len > data.len() {
158 return Err(());
159 }
160 unsafe {
161 ptr::copy_nonoverlapping(src.as_ptr(), data.as_mut_ptr().add(self.offset), count);
162 }
163 self.offset = total_len;
164 Ok(())
165 }
166}
167
168impl<T> From<T> for DataView<T> {
169 #[inline]
170 fn from(data: T) -> Self {
171 Self::new(data)
172 }
173}