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)
33pub struct BuffReader<'a> {
34    buffer: &'a [u8],
35    pub position: usize,
36    len: usize,
37}
38
39impl<'a> BuffReader<'a> {
40    pub fn increment_position(&mut self, increment: usize) {
41        self.position += increment;
42    }
43
44    pub fn new(buffer: &'a [u8], buff_len: usize) -> Self {
45        Self {
46            buffer,
47            position: 0,
48            len: buff_len,
49        }
50    }
51
52    /// Variable byte integer can be 1-4 Bytes long. Buffer reader takes all 4 Bytes at first and
53    /// than check what is true length of varbyteint and increment cursor by that
54    pub fn read_variable_byte_int(&mut self) -> Result<u32, BufferError> {
55        let mut variable_byte_integer: [u8; 4] = [0; 4];
56        let mut len: usize = 1;
57
58        // Everytime checking first bit of Byte which determines whenever there is continuous Byte
59        let mut x = 0;
60        loop {
61            if x >= 4 {
62                break;
63            }
64            if self.position + x >= self.len {
65                return Err(BufferError::InsufficientBufferSize);
66            }
67            if self.buffer[self.position + x] & 0x80 != 0 {
68                variable_byte_integer[x] = self.buffer[self.position + x];
69                len += 1
70            } else {
71                variable_byte_integer[x] = self.buffer[self.position + x];
72                x += 1;
73                if x != 4 {
74                    loop {
75                        variable_byte_integer[x] = 0;
76                        x += 1;
77                        if x == 4 {
78                            break;
79                        }
80                    }
81                    break;
82                }
83            }
84            x += 1;
85        }
86        self.increment_position(len);
87        VariableByteIntegerDecoder::decode(variable_byte_integer)
88    }
89
90    /// Reading u32 from buffer as `Big endian`
91    pub fn read_u32(&mut self) -> Result<u32, BufferError> {
92        if self.position + 4 > self.len {
93            return Err(BufferError::InsufficientBufferSize);
94        }
95        let (int_bytes, _rest) = self.buffer[self.position..].split_at(mem::size_of::<u32>());
96        let ret: u32 = u32::from_be_bytes(int_bytes.try_into().unwrap());
97        self.increment_position(4);
98        Ok(ret)
99    }
100
101    /// Reading u16 from buffer as `Big endinan`
102    pub fn read_u16(&mut self) -> Result<u16, BufferError> {
103        if self.position + 2 > self.len {
104            return Err(BufferError::InsufficientBufferSize);
105        }
106        let (int_bytes, _rest) = self.buffer[self.position..].split_at(mem::size_of::<u16>());
107        let ret: u16 = u16::from_be_bytes(int_bytes.try_into().unwrap());
108        self.increment_position(2);
109        Ok(ret)
110    }
111
112    /// Reading one byte from buffer as `Big endian`
113    pub fn read_u8(&mut self) -> Result<u8, BufferError> {
114        if self.position >= self.len {
115            return Err(BufferError::InsufficientBufferSize);
116        }
117        let ret: u8 = self.buffer[self.position];
118        self.increment_position(1);
119        Ok(ret)
120    }
121
122    /// Reading UTF-8 encoded string from buffer
123    pub fn read_string(&mut self) -> Result<EncodedString<'a>, BufferError> {
124        let len = self.read_u16()? as usize;
125
126        if self.position + len > self.len {
127            return Err(BufferError::InsufficientBufferSize);
128        }
129
130        let res_str = str::from_utf8(&(self.buffer[self.position..(self.position + len)]));
131        if res_str.is_err() {
132            error!("Could not parse utf-8 string");
133            return Err(BufferError::Utf8Error);
134        }
135        self.increment_position(len);
136        Ok(EncodedString {
137            string: res_str.unwrap(),
138            len: len as u16,
139        })
140    }
141
142    /// Read Binary data from buffer
143    pub fn read_binary(&mut self) -> Result<BinaryData<'a>, BufferError> {
144        let len = self.read_u16()?;
145
146        if self.position + len as usize > self.len {
147            return Err(BufferError::InsufficientBufferSize);
148        }
149
150        let res_bin = &(self.buffer[self.position..(self.position + len as usize)]);
151        Ok(BinaryData { bin: res_bin, len })
152    }
153
154    /// Read string pair from buffer
155    pub fn read_string_pair(&mut self) -> Result<StringPair<'a>, BufferError> {
156        let name = self.read_string()?;
157        let value = self.read_string()?;
158        Ok(StringPair { name, value })
159    }
160
161    /// Read payload message from buffer
162    pub fn read_message(&mut self, total_len: usize) -> &'a [u8] {
163        if total_len > self.len {
164            return &self.buffer[self.position..self.len];
165        }
166        &self.buffer[self.position..total_len]
167    }
168
169    /// Peeking (without incremental internal pointer) one byte from buffer as `Big endian`
170    pub fn peek_u8(&self) -> Result<u8, BufferError> {
171        if self.position >= self.len {
172            return Err(BufferError::InsufficientBufferSize);
173        }
174        Ok(self.buffer[self.position])
175    }
176}