byte_transcoder/
reader.rs

1use std::convert::TryInto;
2use uuid::Uuid;
3
4use crate::reader_error::{ByteReaderError, ByteReaderResult};
5
6#[expect(clippy::module_name_repetitions)]
7pub struct ByteReader<'a> {
8    data: &'a [u8],
9    index: usize,
10}
11
12impl<'a> ByteReader<'a> {
13    #[must_use]
14    pub fn new(data: &'a [u8]) -> Self {
15        ByteReader { data, index: 0 }
16    }
17
18    /// # Errors
19    ///
20    /// Will return an error if there are not enough bytes to read.
21    pub fn read_u8(&mut self) -> ByteReaderResult<u8> {
22        if self.index >= self.data.len() {
23            return Err(ByteReaderError::NotEnoughBytes {
24                index_offset: self.index,
25                buffer_length: self.data.len(),
26            });
27        }
28
29        let value: u8 = self.data[self.index];
30        self.index += 1;
31        Ok(value)
32    }
33
34    /// # Errors
35    ///
36    /// Will return an error if there are not enough bytes to read.
37    pub fn read_u16(&mut self) -> ByteReaderResult<u16> {
38        let index_offset: usize = self.index + 2;
39        if index_offset > self.data.len() {
40            return Err(ByteReaderError::NotEnoughBytes {
41                index_offset,
42                buffer_length: self.data.len(),
43            });
44        }
45
46        let u16_bytes: [u8; 2] = self.data[self.index..index_offset]
47            .try_into()
48            .map_err(|_| ByteReaderError::SliceConversionFailure)?;
49        let value: u16 = u16::from_le_bytes(u16_bytes);
50        self.index = index_offset;
51        Ok(value)
52    }
53
54    /// # Errors
55    ///
56    /// Will return an error if there are not enough bytes to read.
57    pub fn read_u32(&mut self) -> ByteReaderResult<u32> {
58        let index_offset: usize = self.index + 4;
59        if index_offset > self.data.len() {
60            return Err(ByteReaderError::NotEnoughBytes {
61                index_offset,
62                buffer_length: self.data.len(),
63            });
64        }
65
66        let u32_bytes: [u8; 4] = self.data[self.index..index_offset]
67            .try_into()
68            .map_err(|_| ByteReaderError::SliceConversionFailure)?;
69        let value: u32 = u32::from_le_bytes(u32_bytes);
70        self.index = index_offset;
71        Ok(value)
72    }
73
74    /// # Errors
75    ///
76    /// Will return an error if there are not enough bytes to read.
77    pub fn read_u64(&mut self) -> ByteReaderResult<u64> {
78        let index_offset: usize = self.index + 8;
79        if index_offset > self.data.len() {
80            return Err(ByteReaderError::NotEnoughBytes {
81                index_offset,
82                buffer_length: self.data.len(),
83            });
84        }
85
86        let u64_bytes: [u8; 8] = self.data[self.index..index_offset]
87            .try_into()
88            .map_err(|_| ByteReaderError::SliceConversionFailure)?;
89        let value: u64 = u64::from_le_bytes(u64_bytes);
90        self.index = index_offset;
91        Ok(value)
92    }
93
94    /// # Errors
95    ///
96    /// Will return an error if there are not enough bytes to read or if the UTF-8 bytes are invalid.
97    pub fn read_string(&mut self) -> ByteReaderResult<String> {
98        let length: usize = self.read_u8()? as usize;
99        let index_offset: usize = self.index + length;
100        if index_offset > self.data.len() {
101            return Err(ByteReaderError::NotEnoughBytes {
102                index_offset,
103                buffer_length: self.data.len(),
104            });
105        }
106
107        let string_bytes: &[u8] = &self.data[self.index..index_offset];
108        self.index = index_offset;
109        String::from_utf8(string_bytes.to_vec()).map_err(|_| ByteReaderError::InvalidUtf8)
110    }
111
112    /// # Errors
113    ///
114    /// Will return an error if there are not enough bytes to read or if the UUID bytes are invalid.
115    pub fn read_uuid(&mut self) -> ByteReaderResult<Uuid> {
116        let index_offset: usize = self.index + 16;
117        if index_offset > self.data.len() {
118            return Err(ByteReaderError::NotEnoughBytes {
119                index_offset,
120                buffer_length: self.data.len(),
121            });
122        }
123
124        let uuid_bytes: [u8; 16] = self.data[self.index..index_offset]
125            .try_into()
126            .map_err(|_| ByteReaderError::SliceConversionFailure)?;
127        self.index = index_offset;
128        Ok(Uuid::from_bytes(uuid_bytes))
129    }
130
131    #[must_use]
132    pub fn read_remaining_bytes(&mut self) -> Vec<u8> {
133        let remaining: Vec<u8> = self.data[self.index..].to_vec();
134        self.index = self.data.len(); // Move the position to the end
135        remaining
136    }
137
138    #[must_use]
139    pub fn is_empty(&self) -> bool {
140        self.index >= self.data.len()
141    }
142
143    #[must_use]
144    pub fn remaining(&self) -> usize {
145        self.data.len() - self.index
146    }
147}