byte_transcoder/
reader.rs

1use std::convert::TryInto;
2use uuid::Uuid;
3
4use crate::{
5    endian::Endian,
6    reader_error::{ByteReaderError, ByteReaderResult},
7};
8
9#[expect(clippy::module_name_repetitions)]
10pub struct ByteReader<'a> {
11    data: &'a [u8],
12    index: usize,
13    endian: Endian,
14}
15
16impl<'a> ByteReader<'a> {
17    #[must_use]
18    pub fn new(data: &'a [u8], endian: Endian) -> Self {
19        ByteReader {
20            data,
21            index: 0,
22            endian,
23        }
24    }
25
26    /// # Errors
27    ///
28    /// Will return an error if there are not enough bytes to read.
29    pub fn read_u8(&mut self) -> ByteReaderResult<u8> {
30        if self.index >= self.data.len() {
31            return Err(ByteReaderError::NotEnoughBytes {
32                index_offset: self.index,
33                buffer_length: self.data.len(),
34            });
35        }
36
37        let value: u8 = match self.endian {
38            Endian::Little => u8::from_le_bytes([self.data[self.index]]),
39            Endian::Big => u8::from_be_bytes([self.data[self.index]]),
40        };
41        self.index += 1;
42        Ok(value)
43    }
44
45    /// # Errors
46    ///
47    /// Will return an error if there are not enough bytes to read.
48    pub fn read_i8(&mut self) -> ByteReaderResult<i8> {
49        if self.index >= self.data.len() {
50            return Err(ByteReaderError::NotEnoughBytes {
51                index_offset: self.index,
52                buffer_length: self.data.len(),
53            });
54        }
55
56        let value: i8 = match self.endian {
57            Endian::Little => i8::from_le_bytes([self.data[self.index]]),
58            Endian::Big => i8::from_be_bytes([self.data[self.index]]),
59        };
60        self.index += 1;
61        Ok(value)
62    }
63
64    /// # Errors
65    ///
66    /// Will return an error if there are not enough bytes to read.
67    pub fn read_u16(&mut self) -> ByteReaderResult<u16> {
68        let index_offset: usize = self.index + 2;
69        if index_offset > self.data.len() {
70            return Err(ByteReaderError::NotEnoughBytes {
71                index_offset,
72                buffer_length: self.data.len(),
73            });
74        }
75
76        let u16_bytes: [u8; 2] = self.data[self.index..index_offset]
77            .try_into()
78            .map_err(|_| ByteReaderError::SliceConversionFailure)?;
79        let value: u16 = match self.endian {
80            Endian::Little => u16::from_le_bytes(u16_bytes),
81            Endian::Big => u16::from_be_bytes(u16_bytes),
82        };
83        self.index = index_offset;
84        Ok(value)
85    }
86
87    /// # Errors
88    ///
89    /// Will return an error if there are not enough bytes to read.
90    pub fn read_i16(&mut self) -> ByteReaderResult<i16> {
91        let index_offset: usize = self.index + 2;
92        if index_offset > self.data.len() {
93            return Err(ByteReaderError::NotEnoughBytes {
94                index_offset,
95                buffer_length: self.data.len(),
96            });
97        }
98
99        let i16_bytes: [u8; 2] = self.data[self.index..index_offset]
100            .try_into()
101            .map_err(|_| ByteReaderError::SliceConversionFailure)?;
102        let value: i16 = match self.endian {
103            Endian::Little => i16::from_le_bytes(i16_bytes),
104            Endian::Big => i16::from_be_bytes(i16_bytes),
105        };
106        self.index = index_offset;
107        Ok(value)
108    }
109
110    /// # Errors
111    ///
112    /// Will return an error if there are not enough bytes to read.
113    pub fn read_u32(&mut self) -> ByteReaderResult<u32> {
114        let index_offset: usize = self.index + 4;
115        if index_offset > self.data.len() {
116            return Err(ByteReaderError::NotEnoughBytes {
117                index_offset,
118                buffer_length: self.data.len(),
119            });
120        }
121
122        let u32_bytes: [u8; 4] = self.data[self.index..index_offset]
123            .try_into()
124            .map_err(|_| ByteReaderError::SliceConversionFailure)?;
125        let value: u32 = match self.endian {
126            Endian::Little => u32::from_le_bytes(u32_bytes),
127            Endian::Big => u32::from_be_bytes(u32_bytes),
128        };
129        self.index = index_offset;
130        Ok(value)
131    }
132
133    /// # Errors
134    ///
135    /// Will return an error if there are not enough bytes to read.
136    pub fn read_i32(&mut self) -> ByteReaderResult<i32> {
137        let index_offset: usize = self.index + 4;
138        if index_offset > self.data.len() {
139            return Err(ByteReaderError::NotEnoughBytes {
140                index_offset,
141                buffer_length: self.data.len(),
142            });
143        }
144
145        let i32_bytes: [u8; 4] = self.data[self.index..index_offset]
146            .try_into()
147            .map_err(|_| ByteReaderError::SliceConversionFailure)?;
148        let value: i32 = match self.endian {
149            Endian::Little => i32::from_le_bytes(i32_bytes),
150            Endian::Big => i32::from_be_bytes(i32_bytes),
151        };
152        self.index = index_offset;
153        Ok(value)
154    }
155
156    /// # Errors
157    ///
158    /// Will return an error if there are not enough bytes to read.
159    pub fn read_u64(&mut self) -> ByteReaderResult<u64> {
160        let index_offset: usize = self.index + 8;
161        if index_offset > self.data.len() {
162            return Err(ByteReaderError::NotEnoughBytes {
163                index_offset,
164                buffer_length: self.data.len(),
165            });
166        }
167
168        let u64_bytes: [u8; 8] = self.data[self.index..index_offset]
169            .try_into()
170            .map_err(|_| ByteReaderError::SliceConversionFailure)?;
171        let value: u64 = match self.endian {
172            Endian::Little => u64::from_le_bytes(u64_bytes),
173            Endian::Big => u64::from_be_bytes(u64_bytes),
174        };
175        self.index = index_offset;
176        Ok(value)
177    }
178
179    /// # Errors
180    ///
181    /// Will return an error if there are not enough bytes to read.
182    pub fn read_i64(&mut self) -> ByteReaderResult<i64> {
183        let index_offset: usize = self.index + 8;
184        if index_offset > self.data.len() {
185            return Err(ByteReaderError::NotEnoughBytes {
186                index_offset,
187                buffer_length: self.data.len(),
188            });
189        }
190
191        let i64_bytes: [u8; 8] = self.data[self.index..index_offset]
192            .try_into()
193            .map_err(|_| ByteReaderError::SliceConversionFailure)?;
194        let value: i64 = match self.endian {
195            Endian::Little => i64::from_le_bytes(i64_bytes),
196            Endian::Big => i64::from_be_bytes(i64_bytes),
197        };
198        self.index = index_offset;
199        Ok(value)
200    }
201
202    /// # Errors
203    ///
204    /// Will return an error if there are not enough bytes to read or if the UTF-8 bytes are invalid.
205    pub fn read_string(&mut self) -> ByteReaderResult<String> {
206        let length: usize = self.read_u8()? as usize;
207        let index_offset: usize = self.index + length;
208        if index_offset > self.data.len() {
209            return Err(ByteReaderError::NotEnoughBytes {
210                index_offset,
211                buffer_length: self.data.len(),
212            });
213        }
214
215        let string_bytes: &[u8] = &self.data[self.index..index_offset];
216        self.index = index_offset;
217        String::from_utf8(string_bytes.to_vec()).map_err(|_| ByteReaderError::InvalidUtf8)
218    }
219
220    /// # Errors
221    ///
222    /// Will return an error if there are not enough bytes to read or if the UUID bytes are invalid.
223    pub fn read_uuid(&mut self) -> ByteReaderResult<Uuid> {
224        let index_offset: usize = self.index + 16;
225        if index_offset > self.data.len() {
226            return Err(ByteReaderError::NotEnoughBytes {
227                index_offset,
228                buffer_length: self.data.len(),
229            });
230        }
231
232        let uuid_bytes: [u8; 16] = self.data[self.index..index_offset]
233            .try_into()
234            .map_err(|_| ByteReaderError::SliceConversionFailure)?;
235        self.index = index_offset;
236        Ok(Uuid::from_bytes(uuid_bytes))
237    }
238
239    #[must_use]
240    pub fn read_remaining_bytes(&mut self) -> Vec<u8> {
241        let remaining: Vec<u8> = self.data[self.index..].to_vec();
242        self.index = self.data.len(); // Move the position to the end
243        remaining
244    }
245
246    #[must_use]
247    pub fn is_empty(&self) -> bool {
248        self.index >= self.data.len()
249    }
250
251    #[must_use]
252    pub fn remaining(&self) -> usize {
253        self.data.len() - self.index
254    }
255}