diff --git a/example_connect.bin b/example_connect.bin new file mode 100644 index 0000000..67dd3eb --- /dev/null +++ b/example_connect.bin @@ -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 \ No newline at end of file diff --git a/src/encoding/mod.rs b/src/encoding/mod.rs new file mode 100644 index 0000000..9ba016a --- /dev/null +++ b/src/encoding/mod.rs @@ -0,0 +1 @@ +pub mod variable_byte_integer; \ No newline at end of file diff --git a/src/encoding/variable_byte_integer.rs b/src/encoding/variable_byte_integer.rs new file mode 100644 index 0000000..025a602 --- /dev/null +++ b/src/encoding/variable_byte_integer.rs @@ -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 { + 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); + } +} \ No newline at end of file