rust_mqtt/utils/
buffer_reader.rs

1/*
2 * MIT License
3 *
4 * Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25use core::mem;
26use core::str;
27
28use crate::encoding::variable_byte_integer::VariableByteIntegerDecoder;
29use crate::utils::types::{BinaryData, BufferError, EncodedString, StringPair};
30
31/// Buff reader is reading corresponding types from buffer (Byte array) and stores current position
32/// (later as cursor)
33/// In case of failure, the BuffReader remains in the same state as before the method call.
34pub struct BuffReader<'a> {
35    buffer: &'a [u8],
36    pub position: usize,
37    len: usize,
38}
39
40impl<'a> BuffReader<'a> {
41    pub fn increment_position(&mut self, increment: usize) {
42        self.position += increment;
43    }
44
45    pub fn new(buffer: &'a [u8], buff_len: usize) -> Self {
46        Self {
47            buffer,
48            position: 0,
49            len: buff_len,
50        }
51    }
52
53    /// Variable byte integer can be 1-4 Bytes long. Buffer reader takes all 4 Bytes at first and
54    /// than check what is true length of varbyteint and increment cursor by that
55    pub fn read_variable_byte_int(&mut self) -> Result<u32, BufferError> {
56        let mut variable_byte_integer: [u8; 4] = [0; 4];
57        let mut len: usize = 1;
58
59        // Everytime checking first bit of Byte which determines whenever there is continuous Byte
60        let mut x = 0;
61        loop {
62            if x >= 4 {
63                break;
64            }
65            if self.position + x >= self.len {
66                return Err(BufferError::InsufficientBufferSize);
67            }
68            if self.buffer[self.position + x] & 0x80 != 0 {
69                variable_byte_integer[x] = self.buffer[self.position + x];
70                len += 1
71            } else {
72                variable_byte_integer[x] = self.buffer[self.position + x];
73                x += 1;
74                if x != 4 {
75                    loop {
76                        variable_byte_integer[x] = 0;
77                        x += 1;
78                        if x == 4 {
79                            break;
80                        }
81                    }
82                    break;
83                }
84            }
85            x += 1;
86        }
87        self.increment_position(len);
88        VariableByteIntegerDecoder::decode(variable_byte_integer)
89    }
90
91    /// Reading u32 from buffer as `Big endian`
92    pub fn read_u32(&mut self) -> Result<u32, BufferError> {
93        if self.position + 4 > self.len {
94            return Err(BufferError::InsufficientBufferSize);
95        }
96        let (int_bytes, _rest) = self.buffer[self.position..].split_at(mem::size_of::<u32>());
97        let ret: u32 = u32::from_be_bytes(int_bytes.try_into().unwrap());
98        self.increment_position(4);
99        Ok(ret)
100    }
101
102    /// Reading u16 from buffer as `Big endinan`
103    pub fn read_u16(&mut self) -> Result<u16, BufferError> {
104        if self.position + 2 > self.len {
105            return Err(BufferError::InsufficientBufferSize);
106        }
107        let (int_bytes, _rest) = self.buffer[self.position..].split_at(mem::size_of::<u16>());
108        let ret: u16 = u16::from_be_bytes(int_bytes.try_into().unwrap());
109        self.increment_position(2);
110        Ok(ret)
111    }
112
113    /// Reading one byte from buffer as `Big endian`
114    pub fn read_u8(&mut self) -> Result<u8, BufferError> {
115        if self.position >= self.len {
116            return Err(BufferError::InsufficientBufferSize);
117        }
118        let ret: u8 = self.buffer[self.position];
119        self.increment_position(1);
120        Ok(ret)
121    }
122
123    /// Reading UTF-8 encoded string from buffer
124    pub fn read_string(&mut self) -> Result<EncodedString<'a>, BufferError> {
125        let len = self.read_u16()? as usize;
126
127        if self.position + len > self.len {
128            self.position -= 2;
129            return Err(BufferError::InsufficientBufferSize);
130        }
131
132        let res_str = str::from_utf8(&(self.buffer[self.position..(self.position + len)]));
133        if res_str.is_err() {
134            self.position -= 2;
135            error!("Could not parse utf-8 string");
136            return Err(BufferError::Utf8Error);
137        }
138        self.increment_position(len);
139        Ok(EncodedString {
140            string: res_str.unwrap(),
141            len: len as u16,
142        })
143    }
144
145    /// Read Binary data from buffer
146    pub fn read_binary(&mut self) -> Result<BinaryData<'a>, BufferError> {
147        let len = self.read_u16()?;
148
149        if self.position + len as usize > self.len {
150            self.position -= 2;
151            return Err(BufferError::InsufficientBufferSize);
152        }
153
154        let res_bin = &(self.buffer[self.position..(self.position + len as usize)]);
155        self.increment_position(len.into());
156        Ok(BinaryData { bin: res_bin, len })
157    }
158
159    /// Read string pair from buffer
160    pub fn read_string_pair(&mut self) -> Result<StringPair<'a>, BufferError> {
161        let starting_position = self.position;
162        let name = self.read_string()?;
163        let len_name = self.position - starting_position;
164
165        match self.read_string() {
166            Ok(value) => Ok(StringPair { name, value }),
167            Err(e) => {
168                self.position -= len_name;
169                Err(e)
170            },
171        }
172    }
173
174    /// Read payload message from buffer
175    pub fn read_message(&mut self, total_len: usize) -> &'a [u8] {
176        if total_len > self.len {
177            return &self.buffer[self.position..self.len];
178        }
179        &self.buffer[self.position..total_len]
180    }
181
182    /// Peeking (without incremental internal pointer) one byte from buffer as `Big endian`
183    pub fn peek_u8(&self) -> Result<u8, BufferError> {
184        if self.position >= self.len {
185            return Err(BufferError::InsufficientBufferSize);
186        }
187        Ok(self.buffer[self.position])
188    }
189}