Encoding&Decoding

This commit is contained in:
Ondrej Babec 2022-02-06 13:44:26 +01:00
parent 0c773fbf0c
commit f0b9a1a272
No known key found for this signature in database
GPG Key ID: 13E577E3769B2079
3 changed files with 116 additions and 0 deletions

31
example_connect.bin Normal file
View File

@ -0,0 +1,31 @@
CONNECT
Hex:
10 10 00 04 4d 51 54 54 05 02 00 3c 03 21 00 14
00 00
Bin:
TYPE LEN PROTOCOL NAME
0001 0000 0001 0000 0000 0000 0000 0100 0100 1101 0101 0001
PROTOCOL NAME VERSION FLAGS KEEP ALIVE
0101 0100 0101 0100 0000 0101 0000 0010 0000 0000 0011 1100
PROP LEN . PROPERTIES . CLIENT ID LEN
0000 0011 0010 0001 0000 0000 0001 0100 0000 0000 0000 0000
PUBLISH
30 18 00 0a 74 65 73 74 2f 74 6f 70 69 63 00 68
65 6c 6c 6f 20 77 6f 72 6c 64
0011 0000 0001 1000 0000 0000 0000 1010 0111 0100 0110 0101
0111 0011 0111 0100 0010 1111 0111 0100 0110 1111 0111 0000
0110 1001 0110 0011 0000 0000 0110 1000 0110 0101 0110 1100
0110 1100 0110 1111 0010 0000 0111 0111 0110 1111 0111 0010
0110 1100 0110 0100
Variable int
- LS 7 bitu jsou data
- MS bit urcuje, jestli nasleduje dalsi byte
b3 01 = 179
1001 0011 0000 0001
00000000 1 0001 0011

1
src/encoding/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod variable_byte_integer;

View File

@ -0,0 +1,84 @@
#![crate_name = "doc"]
/// VariableByteIntegerEncoder and VariableByteIntegerDecoder are implemented based on
/// pseudo code which is introduced in MQTT version 5.0 OASIS standard accesible from
/// https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901107
/// Variable byte integer encoder structure is help structure which implements function used to
/// encode integer into MQTT variable byte integer format. This format is mainly used to encode
/// lenghts stored in a packet.
pub struct VariableByteIntegerEncoder;
/// Variable byte integers error enumeration is used by both encoder and decoder for
/// error notification.
pub enum VariableByteIntegerError {
EncodingError,
DecodingError
}
impl VariableByteIntegerEncoder {
/// Encode function takes as parameter integer as u32 type and encodes
/// this integer into maximal 4 Bytes. MSb of each Byte is controll bit.
/// This bit is saying if there is continuing Byte in stream or not, this way
/// we can effectively use 1 to 4 Bytes based in integer len.
pub fn encode(mut target: u32) -> Result<[u8; 4], VariableByteIntegerError> {
// General known informations from OASIS
const MAX_ENCODABLE: u32 = 268435455;
const MOD: u32 = 128;
if target > MAX_ENCODABLE {
log::error!("Maximal value of integer for encoding was exceeded");
return Err(VariableByteIntegerError::EncodingError);
}
let mut res: [u8; 4] = [0; 4];
let mut encoded_byte: u8;
let mut i: usize = 0;
loop {
encoded_byte = (target % MOD) as u8;
target = target / 128;
if target > 0 {
encoded_byte = encoded_byte | 128;
}
res[i] = encoded_byte;
i = i + 1;
if target <= 0 {
break;
}
}
return Ok(res);
}
}
/// Variable byte integer decoder structure is help structure which implements function used to
/// decode message lenghts in MQTT packet and other parts encoded into variable byte integer.
pub struct VariableByteIntegerDecoder;
impl VariableByteIntegerDecoder {
/// Decode function takes as paramater encoded integer represented
/// as array of 4 unsigned numbers of exactly 1 Byte each -> 4 Bytes maximal
/// same as maximal amount of bytes for variable byte encoding in MQTT.
pub fn decode(encoded: [u8; 4]) -> Result<u32, VariableByteIntegerError> {
let mut multiplier: u32 = 1;
let mut ret: u32 = 0;
let mut encoded_byte: u8;
let mut i: usize = 0;
loop {
encoded_byte = encoded[i];
i = i + 1;
ret = ret + ((encoded_byte & 127) as u32 * multiplier) as u32;
if multiplier > 128 * 128 * 128 {
return Err(VariableByteIntegerError::DecodingError);
}
multiplier = multiplier * 128;
if (encoded_byte & 128) == 0 {
break;
}
}
return Ok(ret);
}
}