Tests
This commit is contained in:
parent
ff287dc451
commit
edb07d94d3
|
@ -22,25 +22,33 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::packet::v5::publish_packet::QualityOfService;
|
||||
use crate::utils::types::{BinaryData, EncodedString};
|
||||
|
||||
pub struct ClientConfig<'a> {
|
||||
pub struct ClientConfig<'a, const MAX_PROPERTIES: usize> {
|
||||
pub qos: QualityOfService,
|
||||
pub keep_alive: u16,
|
||||
pub client_id: EncodedString<'a>,
|
||||
pub username_flag: bool,
|
||||
pub username: EncodedString<'a>,
|
||||
pub password_flag: bool,
|
||||
pub password: BinaryData<'a>,
|
||||
pub properties: Vec<Property<'a>, MAX_PROPERTIES>,
|
||||
}
|
||||
|
||||
impl ClientConfig<'a> {
|
||||
impl<'a, const MAX_PROPERTIES: usize> ClientConfig<'a, MAX_PROPERTIES> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
qos: QualityOfService::QoS0,
|
||||
keep_alive: 60,
|
||||
client_id: EncodedString::new(),
|
||||
username_flag: false,
|
||||
username: EncodedString::new(),
|
||||
password_flag: false,
|
||||
password: BinaryData::new(),
|
||||
properties: Vec::<Property<'a>, MAX_PROPERTIES>::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,4 +71,10 @@ impl ClientConfig<'a> {
|
|||
self.password = password_s;
|
||||
self.password_flag = true;
|
||||
}
|
||||
|
||||
pub fn add_property(&mut self, prop: Property<'a>) {
|
||||
if self.properties.len() < MAX_PROPERTIES {
|
||||
self.properties.push(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ pub struct MqttClientV5<'a, T, const MAX_PROPERTIES: usize> {
|
|||
recv_buffer: &'a mut [u8],
|
||||
recv_buffer_len: usize,
|
||||
rng: CountingRng,
|
||||
config: ClientConfig<'a>,
|
||||
config: ClientConfig<'a, MAX_PROPERTIES>,
|
||||
}
|
||||
|
||||
impl<'a, T, const MAX_PROPERTIES: usize> MqttClientV5<'a, T, MAX_PROPERTIES>
|
||||
|
@ -38,7 +38,7 @@ where
|
|||
buffer_len: usize,
|
||||
recv_buffer: &'a mut [u8],
|
||||
recv_buffer_len: usize,
|
||||
config: ClientConfig<'a>,
|
||||
config: ClientConfig<'a, MAX_PROPERTIES>,
|
||||
) -> Self {
|
||||
Self {
|
||||
network_driver,
|
||||
|
@ -54,6 +54,7 @@ where
|
|||
pub async fn connect_to_broker<'b>(&'b mut self) -> Result<(), ReasonCode> {
|
||||
let len = {
|
||||
let mut connect = ConnectPacket::<'b, 3, 0>::clean();
|
||||
connect.keep_alive = self.config.keep_alive;
|
||||
if self.config.username_flag {
|
||||
connect.add_username(&self.config.username);
|
||||
}
|
||||
|
|
|
@ -37,3 +37,4 @@ pub mod network;
|
|||
pub mod packet;
|
||||
pub mod tokio_network;
|
||||
pub mod utils;
|
||||
pub mod tests;
|
||||
|
|
|
@ -24,6 +24,10 @@ pub trait Network {
|
|||
where
|
||||
Self: 'm;
|
||||
|
||||
type TimerFuture<'m>: Future<Output = ()>
|
||||
where
|
||||
Self: 'm;
|
||||
|
||||
fn new(ip: [u8; 4], port: u16) -> Self;
|
||||
|
||||
fn create_connection(&'m mut self) -> Self::ConnectionFuture<'m>;
|
||||
|
@ -31,4 +35,6 @@ pub trait Network {
|
|||
fn send(&'m mut self, buffer: &'m mut [u8], len: usize) -> Self::WriteFuture<'m>;
|
||||
|
||||
fn receive(&'m mut self, buffer: &'m mut [u8]) -> Self::ReadFuture<'m>;
|
||||
|
||||
fn count_down(&'m mut self, time_in_secs: u64) -> Self::TimerFuture<'m>;
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for AuthPacket<'a, MAX_PROPERTI
|
|||
buff_writer.write_variable_byte_int(rm_ln)?;
|
||||
buff_writer.write_u8(self.auth_reason)?;
|
||||
buff_writer.write_variable_byte_int(self.property_len)?;
|
||||
buff_writer.encode_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.write_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
Ok(buff_writer.position)
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,10 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for AuthPacket<'a, MAX_PROPERTI
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.auth_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -43,18 +43,6 @@ pub struct ConnackPacket<'a, const MAX_PROPERTIES: usize> {
|
|||
}
|
||||
|
||||
impl<'a, const MAX_PROPERTIES: usize> ConnackPacket<'a, MAX_PROPERTIES> {
|
||||
pub fn decode_connack_packet(
|
||||
&mut self,
|
||||
buff_reader: &mut BuffReader<'a>,
|
||||
) -> Result<(), BufferError> {
|
||||
if self.decode_fixed_header(buff_reader)? != (PacketType::Connack).into() {
|
||||
log::error!("Packet you are trying to decode is not CONNACK packet!");
|
||||
return Err(BufferError::PacketTypeMismatch);
|
||||
}
|
||||
self.ack_flags = buff_reader.read_u8()?;
|
||||
self.connect_reason_code = buff_reader.read_u8()?;
|
||||
self.decode_properties(buff_reader)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for ConnackPacket<'a, MAX_PROPERTIES> {
|
||||
|
@ -80,12 +68,18 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for ConnackPacket<'a, MAX_PROPE
|
|||
buff_writer.write_u8(self.ack_flags)?;
|
||||
buff_writer.write_u8(self.connect_reason_code)?;
|
||||
buff_writer.write_variable_byte_int(self.property_len)?;
|
||||
buff_writer.encode_properties(&self.properties)?;
|
||||
buff_writer.write_properties(&self.properties)?;
|
||||
Ok(buff_writer.position)
|
||||
}
|
||||
|
||||
fn decode(&mut self, buff_reader: &mut BuffReader<'a>) -> Result<(), BufferError> {
|
||||
self.decode_connack_packet(buff_reader)
|
||||
if self.decode_fixed_header(buff_reader)? != (PacketType::Connack).into() {
|
||||
log::error!("Packet you are trying to decode is not CONNACK packet!");
|
||||
return Err(BufferError::PacketTypeMismatch);
|
||||
}
|
||||
self.ack_flags = buff_reader.read_u8()?;
|
||||
self.connect_reason_code = buff_reader.read_u8()?;
|
||||
self.decode_properties(buff_reader)
|
||||
}
|
||||
|
||||
fn set_property_len(&mut self, value: u32) {
|
||||
|
@ -100,6 +94,10 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for ConnackPacket<'a, MAX_PROPE
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.connack_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -68,11 +68,13 @@ impl<'a, const MAX_PROPERTIES: usize, const MAX_WILL_PROPERTIES: usize>
|
|||
property_len: 3,
|
||||
properties: Vec::<Property<'a>, MAX_PROPERTIES>::new(),
|
||||
client_id: EncodedString::new(),
|
||||
/// Will is not supported as it is un-necessary load for embedded
|
||||
will_property_len: 0,
|
||||
will_properties: Vec::<Property<'a>, MAX_WILL_PROPERTIES>::new(),
|
||||
will_topic: EncodedString::new(),
|
||||
will_payload: BinaryData::new(),
|
||||
username: EncodedString::new(),
|
||||
|
||||
password: BinaryData::new(),
|
||||
};
|
||||
|
||||
|
@ -96,6 +98,10 @@ impl<'a, const MAX_PROPERTIES: usize, const MAX_WILL_PROPERTIES: usize>
|
|||
self.password = (*password).clone();
|
||||
self.connect_flags = self.connect_flags | 0x40;
|
||||
}
|
||||
|
||||
pub fn add_client_id(& mut self, id: &EncodedString<'a>) {
|
||||
self.client_id = (*id).clone();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const MAX_PROPERTIES: usize, const MAX_WILL_PROPERTIES: usize> Packet<'a>
|
||||
|
@ -159,12 +165,12 @@ impl<'a, const MAX_PROPERTIES: usize, const MAX_WILL_PROPERTIES: usize> Packet<'
|
|||
buff_writer.write_u8(self.connect_flags)?;
|
||||
buff_writer.write_u16(self.keep_alive)?;
|
||||
buff_writer.write_variable_byte_int(self.property_len)?;
|
||||
buff_writer.encode_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.write_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.write_string_ref(&self.client_id)?;
|
||||
|
||||
if self.connect_flags & 0x04 != 0 {
|
||||
buff_writer.write_variable_byte_int(self.will_property_len)?;
|
||||
buff_writer.encode_properties(&self.will_properties)?;
|
||||
buff_writer.write_properties(&self.will_properties)?;
|
||||
buff_writer.write_string_ref(&self.will_topic)?;
|
||||
buff_writer.write_binary_ref(&self.will_payload)?;
|
||||
}
|
||||
|
@ -197,6 +203,10 @@ impl<'a, const MAX_PROPERTIES: usize, const MAX_WILL_PROPERTIES: usize> Packet<'
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.connect_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -73,13 +73,13 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for DisconnectPacket<'a, MAX_PR
|
|||
buff_writer.write_variable_byte_int(rm_len)?;
|
||||
buff_writer.write_u8(self.disconnect_reason)?;
|
||||
buff_writer.write_variable_byte_int(self.property_len)?;
|
||||
buff_writer.encode_properties(&self.properties)?;
|
||||
buff_writer.write_properties(&self.properties)?;
|
||||
Ok(buff_writer.position)
|
||||
}
|
||||
|
||||
fn decode(&mut self, buff_reader: &mut BuffReader<'a>) -> Result<(), BufferError> {
|
||||
if self.decode_fixed_header(buff_reader)? != (PacketType::Pingresp).into() {
|
||||
log::error!("Packet you are trying to decode is not PUBACK packet!");
|
||||
if self.decode_fixed_header(buff_reader)? != (PacketType::Disconnect).into() {
|
||||
log::error!("Packet you are trying to decode is not DISCONNECT packet!");
|
||||
return Err(BufferError::WrongPacketToDecode);
|
||||
}
|
||||
self.disconnect_reason = buff_reader.read_u8()?;
|
||||
|
@ -98,6 +98,10 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for DisconnectPacket<'a, MAX_PR
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.disconnect_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
use crate::utils::types::BufferError;
|
||||
|
@ -43,6 +44,26 @@ pub trait Packet<'a> {
|
|||
fn get_property_len(&mut self) -> u32;
|
||||
/// Method enables pushing new property into packet properties
|
||||
fn push_to_properties(&mut self, property: Property<'a>);
|
||||
/// Returns if property is allowed for packet
|
||||
fn property_allowed(& mut self, property: & Property<'a>) -> bool;
|
||||
/// Method enables adding properties from client config - each packet decides if property can be used with that or not
|
||||
fn add_properties<const MAX_PROPERTIES: usize>(& mut self, properties: &Vec<Property<'a>, MAX_PROPERTIES>) -> u32 {
|
||||
let mut i = 0;
|
||||
let max = properties.len();
|
||||
let mut res: u32 = 0;
|
||||
loop {
|
||||
let prop = properties.get(i).unwrap();
|
||||
if self.property_allowed(prop) {
|
||||
self.push_to_properties((*prop).clone());
|
||||
res = res + prop.len() as u32 + 1;
|
||||
}
|
||||
i = i + 1;
|
||||
if i == max {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Setter for packet fixed header
|
||||
fn set_fixed_header(&mut self, header: u8);
|
||||
|
|
|
@ -70,6 +70,10 @@ impl<'a> Packet<'a> for PingreqPacket {
|
|||
log::error!("PINGREQ packet does not contain any properties!");
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.pingreq_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ impl<'a> Packet<'a> for PingrespPacket {
|
|||
fn encode(&mut self, buffer: &mut [u8], buffer_len: usize) -> Result<usize, BufferError> {
|
||||
let mut buff_writer = BuffWriter::new(buffer, buffer_len);
|
||||
buff_writer.write_u8(self.fixed_header)?;
|
||||
buff_writer.write_variable_byte_int(0 as u32)?;
|
||||
buff_writer.write_variable_byte_int(self.remain_len)?;
|
||||
Ok(buff_writer.position)
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,10 @@ impl<'a> Packet<'a> for PingrespPacket {
|
|||
log::error!("PINGRESP packet does not contain any properties!");
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.pingresp_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -22,11 +22,13 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use crate::encoding::variable_byte_integer::VariableByteIntegerEncoder;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
use crate::utils::buffer_writer::BuffWriter;
|
||||
use crate::utils::types::{BinaryData, BufferError, EncodedString, StringPair};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone)]
|
||||
pub enum Property<'a> {
|
||||
PayloadFormat(u8),
|
||||
MessageExpiryInterval(u32),
|
||||
|
@ -59,6 +61,142 @@ pub enum Property<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Property<'a> {
|
||||
pub fn connect_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::SessionExpiryInterval(_u) => true,
|
||||
Property::ReceiveMaximum(_u) => true,
|
||||
Property::MaximumPacketSize(_u) => true,
|
||||
Property::TopicAliasMaximum(_u) => true,
|
||||
Property::RequestResponseInformation(_u) => true,
|
||||
Property::RequestProblemInformation(_u) => true,
|
||||
Property::UserProperty(_u) => true,
|
||||
Property::AuthenticationMethod(_u) => true,
|
||||
Property::AuthenticationData(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn connack_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::SessionExpiryInterval(_u) => true,
|
||||
Property::ReceiveMaximum(_u) => true,
|
||||
Property::MaximumQoS(_u) => true,
|
||||
Property::MaximumPacketSize(_u) => true,
|
||||
Property::AssignedClientIdentifier(_u) => true,
|
||||
Property::TopicAliasMaximum(_u) => true,
|
||||
Property::ReasonString(_u) => true,
|
||||
Property::UserProperty(_u) => true,
|
||||
Property::WildcardSubscriptionAvailable(_u) => true,
|
||||
Property::SubscriptionIdentifierAvailable(_u) => true,
|
||||
Property::SharedSubscriptionAvailable(_u) => true,
|
||||
Property::ServerKeepAlive(_u) => true,
|
||||
Property::ResponseInformation(_u) => true,
|
||||
Property::ServerReference(_u) => true,
|
||||
Property::AuthenticationMethod(_u) => true,
|
||||
Property::AuthenticationData(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn publish_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::PayloadFormat(_u) => true,
|
||||
Property::MessageExpiryInterval(_u) => true,
|
||||
Property::TopicAlias(_u) => true,
|
||||
Property::ResponseTopic(_u) => true,
|
||||
Property::CorrelationData(_u) => true,
|
||||
Property::UserProperty(_u) => true,
|
||||
Property::SubscriptionIdentifier(_u) => true,
|
||||
Property::ContentType(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn puback_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::ReasonString(_u) => true,
|
||||
Property::UserProperty(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn pubrec_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::ReasonString(_u) => true,
|
||||
Property::UserProperty(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn pubrel_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::ReasonString(_u) => true,
|
||||
Property::UserProperty(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn pubcomp_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::ReasonString(_u) => true,
|
||||
Property::UserProperty(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn subscribe_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::SubscriptionIdentifier(_u) => true,
|
||||
Property::UserProperty(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn suback_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::ReasonString(_u) => true,
|
||||
Property::UserProperty(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn unsubscribe_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::UserProperty(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn unsuback_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::ReasonString(_u) => true,
|
||||
Property::UserProperty(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn pingreq_property(&self) -> bool {
|
||||
return match self {
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn pingresp_property(&self) -> bool {
|
||||
return match self {
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn disconnect_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::SessionExpiryInterval(_u) => true,
|
||||
Property::ReasonString(_u) => true,
|
||||
Property::UserProperty(_u) => true,
|
||||
Property::ServerReference(_u) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn auth_property(&self) -> bool {
|
||||
return match self {
|
||||
Property::AuthenticationMethod(_u) => true,
|
||||
|
@ -76,7 +214,7 @@ impl<'a> Property<'a> {
|
|||
Property::ContentType(u) => u.len(),
|
||||
Property::ResponseTopic(u) => u.len(),
|
||||
Property::CorrelationData(u) => u.len(),
|
||||
Property::SubscriptionIdentifier(_u) => 4,
|
||||
Property::SubscriptionIdentifier(u) => VariableByteIntegerEncoder::len(VariableByteIntegerEncoder::encode(*u).unwrap()) as u16,
|
||||
Property::SessionExpiryInterval(_u) => 4,
|
||||
Property::AssignedClientIdentifier(u) => u.len(),
|
||||
Property::ServerKeepAlive(_u) => 2,
|
||||
|
|
|
@ -69,7 +69,7 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for PubackPacket<'a, MAX_PROPER
|
|||
buff_writer.write_u16(self.packet_identifier)?;
|
||||
buff_writer.write_u8(self.reason_code)?;
|
||||
buff_writer.write_variable_byte_int(self.property_len)?;
|
||||
buff_writer.encode_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.write_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
Ok(buff_writer.position)
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,10 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for PubackPacket<'a, MAX_PROPER
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.puback_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for PubcompPacket<'a, MAX_PROPE
|
|||
buff_writer.write_u16(self.packet_identifier)?;
|
||||
buff_writer.write_u8(self.reason_code)?;
|
||||
buff_writer.write_variable_byte_int(self.property_len)?;
|
||||
buff_writer.encode_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.write_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
Ok(buff_writer.position)
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,10 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for PubcompPacket<'a, MAX_PROPE
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.pubcomp_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for PublishPacket<'a, MAX_PROPE
|
|||
}
|
||||
|
||||
buff_writer.write_variable_byte_int(self.property_len)?;
|
||||
buff_writer.encode_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.write_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.insert_ref(msg_len as usize, self.message.unwrap())?;
|
||||
Ok(buff_writer.position)
|
||||
}
|
||||
|
@ -165,6 +165,10 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for PublishPacket<'a, MAX_PROPE
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.publish_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for PubrecPacket<'a, MAX_PROPER
|
|||
buff_writer.write_u16(self.packet_identifier)?;
|
||||
buff_writer.write_u8(self.reason_code)?;
|
||||
buff_writer.write_variable_byte_int(self.property_len)?;
|
||||
buff_writer.encode_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.write_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
Ok(buff_writer.position)
|
||||
}
|
||||
|
||||
|
@ -94,6 +94,11 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for PubrecPacket<'a, MAX_PROPER
|
|||
fn push_to_properties(&mut self, property: Property<'a>) {
|
||||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.pubrec_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for PubrelPacket<'a, MAX_PROPER
|
|||
buff_writer.write_u16(self.packet_identifier)?;
|
||||
buff_writer.write_u8(self.reason_code)?;
|
||||
buff_writer.write_variable_byte_int(self.property_len)?;
|
||||
buff_writer.encode_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.write_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
Ok(buff_writer.position)
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,10 @@ impl<'a, const MAX_PROPERTIES: usize> Packet<'a> for PubrelPacket<'a, MAX_PROPER
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.pubrel_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::encoding::variable_byte_integer::VariableByteIntegerEncoder;
|
||||
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
|
@ -47,11 +48,14 @@ impl<'a, const MAX_REASONS: usize, const MAX_PROPERTIES: usize>
|
|||
&mut self,
|
||||
buff_reader: &mut BuffReader<'a>,
|
||||
) -> Result<(), BufferError> {
|
||||
let mut i = 0;
|
||||
let rm_ln_ln = VariableByteIntegerEncoder::len(VariableByteIntegerEncoder::encode(self.remain_len).unwrap());
|
||||
let max = self.remain_len as usize + rm_ln_ln + 1;
|
||||
if buff_reader.position >= max {
|
||||
return Ok(())
|
||||
}
|
||||
loop {
|
||||
self.reason_codes.push(buff_reader.read_u8()?);
|
||||
i = i + 1;
|
||||
if i == MAX_REASONS {
|
||||
if buff_reader.position == max {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +104,10 @@ impl<'a, const MAX_REASONS: usize, const MAX_PROPERTIES: usize> Packet<'a>
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.suback_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -96,8 +96,8 @@ impl<'a, const MAX_FILTERS: usize, const MAX_PROPERTIES: usize> Packet<'a>
|
|||
buff_writer.write_variable_byte_int(rm_ln)?;
|
||||
buff_writer.write_u16(self.packet_identifier)?;
|
||||
buff_writer.write_variable_byte_int(self.property_len)?;
|
||||
buff_writer.encode_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.encode_topic_filters_ref(
|
||||
buff_writer.write_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.write_topic_filters_ref(
|
||||
true,
|
||||
self.topic_filter_len as usize,
|
||||
&self.topic_filters,
|
||||
|
@ -121,6 +121,10 @@ impl<'a, const MAX_FILTERS: usize, const MAX_PROPERTIES: usize> Packet<'a>
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.subscribe_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -100,6 +100,10 @@ impl<'a, const MAX_REASONS: usize, const MAX_PROPERTIES: usize> Packet<'a>
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.unsuback_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ use heapless::Vec;
|
|||
|
||||
use crate::encoding::variable_byte_integer::VariableByteIntegerEncoder;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::publish_packet::QualityOfService;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
use crate::utils::buffer_writer::BuffWriter;
|
||||
use crate::utils::types::{BufferError, TopicFilter};
|
||||
|
@ -45,6 +46,16 @@ pub struct UnsubscriptionPacket<'a, const MAX_FILTERS: usize, const MAX_PROPERTI
|
|||
impl<'a, const MAX_FILTERS: usize, const MAX_PROPERTIES: usize>
|
||||
UnsubscriptionPacket<'a, MAX_FILTERS, MAX_PROPERTIES>
|
||||
{
|
||||
pub fn add_new_filter(&mut self, topic_name: &'a str, qos: QualityOfService) {
|
||||
let len = topic_name.len();
|
||||
let mut new_filter = TopicFilter::new();
|
||||
new_filter.filter.string = topic_name;
|
||||
new_filter.filter.len = len as u16;
|
||||
new_filter.sub_options =
|
||||
new_filter.sub_options | (<QualityOfService as Into<u8>>::into(qos) >> 1);
|
||||
self.topic_filters.push(new_filter);
|
||||
self.topic_filter_len = self.topic_filter_len + 1;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const MAX_FILTERS: usize, const MAX_PROPERTIES: usize> Packet<'a>
|
||||
|
@ -68,15 +79,24 @@ impl<'a, const MAX_FILTERS: usize, const MAX_PROPERTIES: usize> Packet<'a>
|
|||
let mut rm_ln = self.property_len;
|
||||
let property_len_enc: [u8; 4] = VariableByteIntegerEncoder::encode(self.property_len)?;
|
||||
let property_len_len = VariableByteIntegerEncoder::len(property_len_enc);
|
||||
rm_ln = rm_ln + property_len_len as u32 + 4 + self.topic_filter_len as u32;
|
||||
|
||||
let mut lt = 0;
|
||||
let mut filters_len = 0;
|
||||
loop {
|
||||
filters_len = filters_len + self.topic_filters.get(lt).unwrap().filter.len + 2;
|
||||
lt = lt + 1;
|
||||
if lt == self.topic_filter_len as usize {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rm_ln = rm_ln + property_len_len as u32 + 2 + filters_len as u32;
|
||||
|
||||
buff_writer.write_u8(self.fixed_header)?;
|
||||
buff_writer.write_variable_byte_int(rm_ln)?;
|
||||
buff_writer.write_u16(self.packet_identifier)?;
|
||||
buff_writer.write_variable_byte_int(self.property_len)?;
|
||||
buff_writer.encode_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.write_u16(self.topic_filter_len)?;
|
||||
buff_writer.encode_topic_filters_ref(
|
||||
buff_writer.write_properties::<MAX_PROPERTIES>(&self.properties)?;
|
||||
buff_writer.write_topic_filters_ref(
|
||||
false,
|
||||
self.topic_filter_len as usize,
|
||||
&self.topic_filters,
|
||||
|
@ -101,6 +121,10 @@ impl<'a, const MAX_FILTERS: usize, const MAX_PROPERTIES: usize> Packet<'a>
|
|||
self.properties.push(property);
|
||||
}
|
||||
|
||||
fn property_allowed(&mut self, property: &Property<'a>) -> bool {
|
||||
property.unsubscribe_property()
|
||||
}
|
||||
|
||||
fn set_fixed_header(&mut self, header: u8) {
|
||||
self.fixed_header = header;
|
||||
}
|
||||
|
|
26
src/tests/mod.rs
Normal file
26
src/tests/mod.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod unit;
|
28
src/tests/unit/client/client_v5_unit.rs
Normal file
28
src/tests/unit/client/client_v5_unit.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
25
src/tests/unit/client/mod.rs
Normal file
25
src/tests/unit/client/mod.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
pub mod client_v5_unit;
|
25
src/tests/unit/encoding/mod.rs
Normal file
25
src/tests/unit/encoding/mod.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
pub mod variable_byte_integer_unit;
|
78
src/tests/unit/encoding/variable_byte_integer_unit.rs
Normal file
78
src/tests/unit/encoding/variable_byte_integer_unit.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use crate::encoding::variable_byte_integer::{VariableByteInteger, VariableByteIntegerDecoder, VariableByteIntegerEncoder};
|
||||
use crate::utils::types::BufferError;
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
static BUFFER: VariableByteInteger = [0x81, 0x81, 0x81, 0x01];
|
||||
|
||||
let decoded = VariableByteIntegerDecoder::decode(BUFFER);
|
||||
assert!(decoded.is_ok());
|
||||
assert_eq!(decoded.unwrap(), 2113665);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_small() {
|
||||
static BUFFER: VariableByteInteger = [0x81, 0x81, 0x01, 0x85];
|
||||
|
||||
let decoded = VariableByteIntegerDecoder::decode(BUFFER);
|
||||
assert!(decoded.is_ok());
|
||||
assert_eq!(decoded.unwrap(), 16_513);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let encoded = VariableByteIntegerEncoder::encode(211_366_5);
|
||||
assert!(encoded.is_ok());
|
||||
let res = encoded.unwrap();
|
||||
assert_eq!(res, [0x81, 0x81, 0x81, 0x01]);
|
||||
assert_eq!(VariableByteIntegerEncoder::len(res), 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_small() {
|
||||
let encoded = VariableByteIntegerEncoder::encode(16_513);
|
||||
assert!(encoded.is_ok());
|
||||
let res = encoded.unwrap();
|
||||
assert_eq!(res, [0x81, 0x81, 0x01, 0x00]);
|
||||
assert_eq!(VariableByteIntegerEncoder::len(res), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_extra_small() {
|
||||
let encoded = VariableByteIntegerEncoder::encode(5);
|
||||
assert!(encoded.is_ok());
|
||||
let res = encoded.unwrap();
|
||||
assert_eq!(res, [0x05, 0x00, 0x00, 0x00]);
|
||||
assert_eq!(VariableByteIntegerEncoder::len(res), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_max() {
|
||||
let encoded = VariableByteIntegerEncoder::encode(288_435_455);
|
||||
assert!(encoded.is_err());
|
||||
assert_eq!(encoded.unwrap_err(), BufferError::EncodingError);
|
||||
}
|
28
src/tests/unit/mod.rs
Normal file
28
src/tests/unit/mod.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
pub mod utils;
|
||||
pub mod encoding;
|
||||
pub mod packet;
|
||||
pub mod client;
|
25
src/tests/unit/packet/mod.rs
Normal file
25
src/tests/unit/packet/mod.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
pub mod v5;
|
63
src/tests/unit/packet/v5/connack_packet_unit.rs
Normal file
63
src/tests/unit/packet/v5/connack_packet_unit.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use crate::packet::v5::connack_packet::ConnackPacket;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::packet::v5::reason_codes::ReasonCode;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 100] = [0; 100];
|
||||
let mut connack = ConnackPacket::<2>::new();
|
||||
connack.property_len = 3;
|
||||
let prop = Property::ReceiveMaximum(21);
|
||||
connack.properties.push(prop);
|
||||
connack.connect_reason_code = ReasonCode::ServerMoved.into();
|
||||
connack.ack_flags = 0x45;
|
||||
|
||||
let res = connack.encode(& mut buffer, 100);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(buffer[0..res.unwrap()], [0x20, 0x06, 0x45, ReasonCode::ServerMoved.into(), 0x03, 0x21, 0x00, 0x15])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
let mut buffer: [u8; 8] = [0x20, 0x06, 0x45, ReasonCode::ServerMoved.into(), 0x03, 0x21, 0x00, 0x15];
|
||||
let mut connack_res = ConnackPacket::<2>::new();
|
||||
let res = connack_res.decode(& mut BuffReader::new(& mut buffer, 8));
|
||||
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(connack_res.property_len, 3);
|
||||
assert_eq!(connack_res.ack_flags, 0x45);
|
||||
assert_eq!(connack_res.connect_reason_code, ReasonCode::ServerMoved.into());
|
||||
assert_eq!(connack_res.property_len, 3);
|
||||
let prop = connack_res.properties.get(0).unwrap();
|
||||
assert_eq!(<&Property as Into<u8>>::into(prop), 0x21);
|
||||
if let Property::ReceiveMaximum(u) = *prop {
|
||||
assert_eq!(u, 21);
|
||||
}
|
||||
|
||||
}
|
38
src/tests/unit/packet/v5/connect_packet_unit.rs
Normal file
38
src/tests/unit/packet/v5/connect_packet_unit.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use crate::packet::v5::connect_packet::ConnectPacket;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 100] = [0; 100];
|
||||
let mut connect = ConnectPacket::<1, 0>::clean();
|
||||
let res = connect.encode(& mut buffer, 100);
|
||||
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(buffer[0..res.unwrap()], [0x10, 0x10, 0x00, 0x04, 0x4d, 0x51,
|
||||
0x54, 0x54, 0x05, 0x02, 0x00, 0x3c,
|
||||
0x03, 0x21, 0x00, 0x14, 0x00, 0x00])
|
||||
}
|
62
src/tests/unit/packet/v5/disconnect_packet_unit.rs
Normal file
62
src/tests/unit/packet/v5/disconnect_packet_unit.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::disconnect_packet::DisconnectPacket;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 10] = [0; 10];
|
||||
let mut packet = DisconnectPacket::<1>::new();
|
||||
let prop: Property = Property::SessionExpiryInterval(512);
|
||||
let mut props = Vec::<Property, 1>::new();
|
||||
props.push(prop);
|
||||
packet.property_len = packet.add_properties(&props);
|
||||
let res = packet.encode(& mut buffer, 100);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(buffer[0..res.unwrap()], [0xE0, 0x07, 0x00, 0x05, 0x11, 0x00, 0x00, 0x02, 0x00])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
let mut buffer: [u8; 10] = [0xE0, 0x07, 0x00, 0x05, 0x11, 0x00, 0x00, 0x04, 0x00, 0x00];
|
||||
let mut packet = DisconnectPacket::<1>::new();
|
||||
let res = packet.decode(& mut BuffReader::new(&buffer, 10));
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(packet.fixed_header, PacketType::Disconnect.into());
|
||||
assert_eq!(packet.remain_len, 7);
|
||||
assert_eq!(packet.disconnect_reason, 0x00);
|
||||
assert_eq!(packet.property_len, 5);
|
||||
let prop = packet.properties.get(0);
|
||||
assert!(prop.is_some());
|
||||
assert_eq!(<&Property as Into<u8>>::into(prop.unwrap()), 0x11);
|
||||
if let Property::SessionExpiryInterval(u) = *prop.unwrap() {
|
||||
assert_eq!(u, 1024);
|
||||
}
|
||||
}
|
38
src/tests/unit/packet/v5/mod.rs
Normal file
38
src/tests/unit/packet/v5/mod.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
pub mod connack_packet_unit;
|
||||
pub mod connect_packet_unit;
|
||||
pub mod disconnect_packet_unit;
|
||||
pub mod pingreq_packet_unit;
|
||||
pub mod pingresp_packet_unit;
|
||||
pub mod puback_packet_unit;
|
||||
pub mod pubcomp_packet_unit;
|
||||
pub mod publish_packet_unit;
|
||||
pub mod pubrec_packet_unit;
|
||||
pub mod pubrel_packet_unit;
|
||||
pub mod suback_packet_unit;
|
||||
pub mod subscription_packet_unit;
|
||||
pub mod unsuback_packet_unit;
|
||||
pub mod unsubscription_packet_unit;
|
38
src/tests/unit/packet/v5/pingreq_packet_unit.rs
Normal file
38
src/tests/unit/packet/v5/pingreq_packet_unit.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::pingreq_packet::PingreqPacket;
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 3] = [0x00, 0x98, 0x45];
|
||||
let mut packet = PingreqPacket::new();
|
||||
packet.fixed_header = PacketType::Pingreq.into();
|
||||
packet.remain_len = 0;
|
||||
let res = packet.encode(& mut buffer, 3);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(buffer, [0xC0, 0x00, 0x45])
|
||||
}
|
49
src/tests/unit/packet/v5/pingresp_packet_unit.rs
Normal file
49
src/tests/unit/packet/v5/pingresp_packet_unit.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::pingresp_packet::PingrespPacket;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 3] = [0x00, 0x98, 0x45];
|
||||
let mut packet = PingrespPacket::new();
|
||||
packet.fixed_header = PacketType::Pingresp.into();
|
||||
packet.remain_len = 0;
|
||||
let res = packet.encode(& mut buffer, 3);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(buffer, [0xD0, 0x00, 0x45])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
let mut buffer: [u8; 3] = [0xD0, 0x00, 0x51];
|
||||
let mut packet = PingrespPacket::new();
|
||||
let res = packet.decode(& mut BuffReader::new(&buffer, 3));
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(packet.fixed_header, PacketType::Pingresp.into());
|
||||
assert_eq!(packet.remain_len, 0);
|
||||
}
|
68
src/tests/unit/packet/v5/puback_packet_unit.rs
Normal file
68
src/tests/unit/packet/v5/puback_packet_unit.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::packet::v5::puback_packet::PubackPacket;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
use crate::utils::types::EncodedString;
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 14] = [0; 14];
|
||||
let mut packet = PubackPacket::<1>::new();
|
||||
packet.packet_identifier = 35420;
|
||||
packet.reason_code = 0x00;
|
||||
let mut str = EncodedString::new();
|
||||
str.string = "Hello";
|
||||
str.len = 5;
|
||||
let mut props = Vec::<Property, 1>::new();
|
||||
props.push(Property::ReasonString(str));
|
||||
packet.property_len = packet.add_properties(&props);
|
||||
let res = packet.encode(& mut buffer, 14);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(res.unwrap(), 14);
|
||||
assert_eq!(buffer, [0x40, 0x0C, 0x8A, 0x5C, 0x00, 0x08, 0x1F, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
let mut buffer: [u8; 14] = [0x40, 0x0C, 0x8A, 0x5E, 0x15, 0x08, 0x1F, 0x00, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f];
|
||||
let mut packet = PubackPacket::<1>::new();
|
||||
let res = packet.decode(& mut BuffReader::new(&buffer, 14));
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(packet.fixed_header, PacketType::Puback.into());
|
||||
assert_eq!(packet.remain_len, 12);
|
||||
assert_eq!(packet.packet_identifier, 35422);
|
||||
assert_eq!(packet.reason_code, 0x15);
|
||||
assert_eq!(packet.property_len, 8);
|
||||
let prop = packet.properties.get(0);
|
||||
assert!(prop.is_some());
|
||||
assert_eq!(<&Property as Into<u8>>::into(prop.unwrap()), 0x1F);
|
||||
if let Property::ReasonString(u) = (*prop.unwrap()).clone() {
|
||||
assert_eq!(u.string, "Hello");
|
||||
}
|
||||
}
|
68
src/tests/unit/packet/v5/pubcomp_packet_unit.rs
Normal file
68
src/tests/unit/packet/v5/pubcomp_packet_unit.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::packet::v5::pubcomp_packet::PubcompPacket;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
use crate::utils::types::EncodedString;
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 14] = [0; 14];
|
||||
let mut packet = PubcompPacket::<1>::new();
|
||||
packet.fixed_header = PacketType::Pubcomp.into();
|
||||
packet.packet_identifier = 35420;
|
||||
packet.reason_code = 0x00;
|
||||
let mut str = EncodedString::new();
|
||||
str.string = "Wheel";
|
||||
str.len = 5;
|
||||
let mut props = Vec::<Property, 1>::new();
|
||||
props.push(Property::ReasonString(str));
|
||||
packet.property_len = packet.add_properties(& props);
|
||||
let res = packet.encode(& mut buffer, 14);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(res.unwrap(), 14);
|
||||
assert_eq!(buffer, [0x70, 0x0C, 0x8A, 0x5C, 0x00, 0x08, 0x1F, 0x00, 0x05, 0x57, 0x68, 0x65, 0x65, 0x6c])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
let mut buffer: [u8; 14] = [0x70, 0x0C, 0x8A, 0x5C, 0x00, 0x08, 0x1F, 0x00, 0x05, 0x57, 0x68, 0x65, 0x65, 0x6c];
|
||||
let mut packet = PubcompPacket::<1>::new();
|
||||
let res = packet.decode(& mut BuffReader::new(&buffer, 14));
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(packet.fixed_header, PacketType::Pubcomp.into());
|
||||
assert_eq!(packet.packet_identifier, 35420);
|
||||
assert_eq!(packet.reason_code, 0x00);
|
||||
assert_eq!(packet.property_len, 8);
|
||||
let prop = packet.properties.get(0);
|
||||
assert!(prop.is_some());
|
||||
assert_eq!(<&Property as Into<u8>>::into(prop.unwrap()), 0x1F);
|
||||
if let Property::ReasonString(u) = (*prop.unwrap()).clone() {
|
||||
assert_eq!(u.string, "Wheel");
|
||||
}
|
||||
}
|
86
src/tests/unit/packet/v5/publish_packet_unit.rs
Normal file
86
src/tests/unit/packet/v5/publish_packet_unit.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::packet::v5::publish_packet::{PublishPacket, QualityOfService};
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
use crate::utils::types::EncodedString;
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 29] = [0; 29];
|
||||
let mut packet = PublishPacket::<2>::new();
|
||||
packet.fixed_header = PacketType::Publish.into();
|
||||
packet.add_qos(QualityOfService::QoS1);
|
||||
let mut topic = EncodedString::new();
|
||||
topic.string = "test";
|
||||
topic.len = 4;
|
||||
packet.topic_name = topic;
|
||||
packet.packet_identifier = 23432;
|
||||
let mut props = Vec::<Property, 2>::new();
|
||||
props.push(Property::PayloadFormat(0x01));
|
||||
props.push(Property::MessageExpiryInterval(45678));
|
||||
packet.property_len = packet.add_properties(&props);
|
||||
static MESSAGE: [u8; 11] = [0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64];
|
||||
packet.add_message(&MESSAGE);
|
||||
let res = packet.encode(& mut buffer, 100);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(res.unwrap(), 29);
|
||||
assert_eq!(buffer, [0x32, 0x1B, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x5B, 0x88,
|
||||
0x07, 0x01, 0x01, 0x02, 0x00, 0x00, 0xB2, 0x6E,
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
let mut buffer:[u8; 29] = [0x32, 0x1B, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x5B, 0x88,
|
||||
0x07, 0x01, 0x01, 0x02, 0x00, 0x00, 0xB2, 0x6E,
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64];
|
||||
let mut packet = PublishPacket::<2>::new();
|
||||
let res = packet.decode(& mut BuffReader::new(&buffer, 29));
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(packet.fixed_header, 0x32);
|
||||
assert_eq!(packet.topic_name.len, 4);
|
||||
assert_eq!(packet.topic_name.string, "test");
|
||||
assert_eq!(packet.packet_identifier, 23432);
|
||||
assert_eq!(packet.property_len, 7);
|
||||
let prop = packet.properties.get(0);
|
||||
assert!(prop.is_some());
|
||||
assert_eq!(<&Property as Into<u8>>::into(prop.unwrap()), 0x01);
|
||||
if let Property::PayloadFormat(u) = (*prop.unwrap()).clone() {
|
||||
assert_eq!(u, 0x01);
|
||||
}
|
||||
let prop2 = packet.properties.get(1);
|
||||
assert!(prop2.is_some());
|
||||
assert_eq!(<&Property as Into<u8>>::into(prop2.unwrap()), 0x02);
|
||||
if let Property::MessageExpiryInterval(u) = (*prop2.unwrap()).clone() {
|
||||
assert_eq!(u, 45678);
|
||||
}
|
||||
if let Some(message) = packet.message {
|
||||
assert_eq!(*message, [0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
|
||||
}
|
||||
}
|
78
src/tests/unit/packet/v5/pubrec_packet_unit.rs
Normal file
78
src/tests/unit/packet/v5/pubrec_packet_unit.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::packet::v5::puback_packet::PubackPacket;
|
||||
use crate::packet::v5::pubrec_packet::PubrecPacket;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
use crate::utils::types::{EncodedString, StringPair};
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 20] = [0; 20];
|
||||
let mut packet = PubrecPacket::<2>::new();
|
||||
packet.packet_identifier = 35420;
|
||||
packet.reason_code = 0x12;
|
||||
let mut name = EncodedString::new();
|
||||
name.string = "name1";
|
||||
name.len = 5;
|
||||
let mut val = EncodedString::new();
|
||||
val.string = "val1";
|
||||
val.len = 4;
|
||||
let mut pair = StringPair::new();
|
||||
pair.name = name;
|
||||
pair.value = val;
|
||||
let mut props = Vec::<Property, 1>::new();
|
||||
props.push(Property::UserProperty(pair));
|
||||
packet.property_len = packet.add_properties(&props);
|
||||
let res = packet.encode(& mut buffer, 20);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(res.unwrap(), 20);
|
||||
assert_eq!(buffer, [0x50, 0x12, 0x8A, 0x5C, 0x12, 0x0E, 0x26, 0x00, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x31, 0x00, 0x04, 0x76, 0x61, 0x6c, 0x31])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
let mut buffer: [u8; 20] = [0x50, 0x12, 0x8A, 0x5C, 0x12, 0x0E, 0x26, 0x00, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x31, 0x00, 0x04, 0x76, 0x61, 0x6c, 0x31];
|
||||
let mut packet = PubrecPacket::<1>::new();
|
||||
let res = packet.decode(& mut BuffReader::new(&buffer, 20));
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(packet.fixed_header, PacketType::Pubrec.into());
|
||||
assert_eq!(packet.remain_len, 18);
|
||||
assert_eq!(packet.packet_identifier, 35420);
|
||||
assert_eq!(packet.reason_code, 0x12);
|
||||
assert_eq!(packet.property_len, 14);
|
||||
let prop = packet.properties.get(0);
|
||||
assert!(prop.is_some());
|
||||
assert_eq!(<&Property as Into<u8>>::into(prop.unwrap()), 0x26);
|
||||
if let Property::UserProperty(u) = (*prop.unwrap()).clone() {
|
||||
assert_eq!(u.name.len, 5);
|
||||
assert_eq!(u.name.string, "name1");
|
||||
assert_eq!(u.value.len, 4);
|
||||
assert_eq!(u.value.string, "val1");
|
||||
}
|
||||
}
|
82
src/tests/unit/packet/v5/pubrel_packet_unit.rs
Normal file
82
src/tests/unit/packet/v5/pubrel_packet_unit.rs
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::packet::v5::puback_packet::PubackPacket;
|
||||
use crate::packet::v5::pubrec_packet::PubrecPacket;
|
||||
use crate::packet::v5::pubrel_packet::PubrelPacket;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
use crate::utils::types::{EncodedString, StringPair};
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 21] = [0; 21];
|
||||
let mut packet = PubrelPacket::<1>::new();
|
||||
packet.fixed_header = PacketType::Pubrel.into();
|
||||
packet.packet_identifier = 12345;
|
||||
packet.reason_code = 0x86;
|
||||
let mut name = EncodedString::new();
|
||||
name.string = "haha";
|
||||
name.len = 4;
|
||||
let mut val = EncodedString::new();
|
||||
val.string = "hehe89";
|
||||
val.len = 6;
|
||||
let mut pair = StringPair::new();
|
||||
pair.name = name;
|
||||
pair.value = val;
|
||||
let mut props = Vec::<Property, 1>::new();
|
||||
props.push(Property::UserProperty(pair));
|
||||
packet.property_len = packet.add_properties(&props);
|
||||
let res = packet.encode(& mut buffer, 21);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(res.unwrap(), 21);
|
||||
assert_eq!(buffer, [0x60, 0x13, 0x30, 0x39, 0x86, 0x0F, 0x26, 0x00, 0x04,
|
||||
0x68, 0x61, 0x68, 0x61, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x38, 0x39])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
let mut buffer: [u8; 21] = [0x60, 0x13, 0x30, 0x39, 0x86, 0x0F, 0x26, 0x00, 0x04,
|
||||
0x68, 0x61, 0x68, 0x61, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x38, 0x39];
|
||||
let mut packet = PubrelPacket::<1>::new();
|
||||
let res = packet.decode(& mut BuffReader::new(&buffer, 21));
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(packet.fixed_header, PacketType::Pubrel.into());
|
||||
assert_eq!(packet.remain_len, 19);
|
||||
assert_eq!(packet.packet_identifier, 12345);
|
||||
assert_eq!(packet.reason_code, 0x86);
|
||||
assert_eq!(packet.property_len, 15);
|
||||
let prop = packet.properties.get(0);
|
||||
assert!(prop.is_some());
|
||||
assert_eq!(<&Property as Into<u8>>::into(prop.unwrap()), 0x26);
|
||||
if let Property::UserProperty(u) = (*prop.unwrap()).clone() {
|
||||
assert_eq!(u.name.len, 4);
|
||||
assert_eq!(u.name.string, "haha");
|
||||
assert_eq!(u.value.len, 6);
|
||||
assert_eq!(u.value.string, "hehe89");
|
||||
}
|
||||
}
|
71
src/tests/unit/packet/v5/suback_packet_unit.rs
Normal file
71
src/tests/unit/packet/v5/suback_packet_unit.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::packet::v5::puback_packet::PubackPacket;
|
||||
use crate::packet::v5::pubrec_packet::PubrecPacket;
|
||||
use crate::packet::v5::pubrel_packet::PubrelPacket;
|
||||
use crate::packet::v5::suback_packet::SubackPacket;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
use crate::utils::types::{EncodedString, StringPair};
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
let mut buffer: [u8; 23] = [0x90, 0x15, 0xCC, 0x08, 0x0F, 0x1F, 0x00, 0x0C,
|
||||
0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x12, 0x34, 0x56];
|
||||
let mut packet = SubackPacket::<3, 1>::new();
|
||||
let res = packet.decode(& mut BuffReader::new(&buffer, 23));
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(packet.fixed_header, PacketType::Suback.into());
|
||||
assert_eq!(packet.remain_len, 21);
|
||||
assert_eq!(packet.packet_identifier, 52232);
|
||||
assert_eq!(packet.property_len, 15);
|
||||
let prop = packet.properties.get(0);
|
||||
assert!(prop.is_some());
|
||||
assert_eq!(<&Property as Into<u8>>::into(prop.unwrap()), 0x1F);
|
||||
if let Property::ReasonString(u) = (*prop.unwrap()).clone() {
|
||||
assert_eq!(u.len, 12);
|
||||
assert_eq!(u.string, "reasonString");
|
||||
}
|
||||
assert_eq!(packet.reason_codes.len(), 3);
|
||||
let res1 = packet.reason_codes.get(0);
|
||||
assert!(res1.is_some());
|
||||
if let Some(r) = res1 {
|
||||
assert_eq!(*r, 0x12);
|
||||
}
|
||||
let res2 = packet.reason_codes.get(1);
|
||||
assert!(res2.is_some());
|
||||
if let Some(r) = res2 {
|
||||
assert_eq!(*r, 0x34);
|
||||
}
|
||||
let res3 = packet.reason_codes.get(2);
|
||||
assert!(res3.is_some());
|
||||
if let Some(r) = res3 {
|
||||
assert_eq!(*r, 0x56);
|
||||
}
|
||||
}
|
49
src/tests/unit/packet/v5/subscription_packet_unit.rs
Normal file
49
src/tests/unit/packet/v5/subscription_packet_unit.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::packet::v5::publish_packet::QualityOfService::{QoS0, QoS1};
|
||||
use crate::packet::v5::subscription_packet::SubscriptionPacket;
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 30] = [0; 30];
|
||||
let mut packet = SubscriptionPacket::<2, 1>::new();
|
||||
packet.fixed_header = PacketType::Subscribe.into();
|
||||
packet.packet_identifier = 5432;
|
||||
let mut props = Vec::<Property, 2>::new();
|
||||
props.push(Property::SubscriptionIdentifier(2432));
|
||||
packet.property_len = packet.add_properties(&props);
|
||||
packet.add_new_filter("test/topic", QoS0);
|
||||
packet.add_new_filter("hehe/#", QoS1);
|
||||
let res = packet.encode(& mut buffer, 30);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(res.unwrap(), 30);
|
||||
assert_eq!(buffer, [0x82, 0x1C, 0x15, 0x38, 0x03, 0x0B, 0x80, 0x13, 0x00, 0x0A,
|
||||
0x74, 0x65, 0x73, 0x74, 0x2f, 0x74, 0x6f, 0x70, 0x69, 0x63,
|
||||
0x00, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x2F, 0x23, 0x01]);
|
||||
}
|
67
src/tests/unit/packet/v5/unsuback_packet_unit.rs
Normal file
67
src/tests/unit/packet/v5/unsuback_packet_unit.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::packet::v5::puback_packet::PubackPacket;
|
||||
use crate::packet::v5::pubrec_packet::PubrecPacket;
|
||||
use crate::packet::v5::pubrel_packet::PubrelPacket;
|
||||
use crate::packet::v5::suback_packet::SubackPacket;
|
||||
use crate::packet::v5::unsuback_packet::UnsubackPacket;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
use crate::utils::types::{EncodedString, StringPair};
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
let mut buffer: [u8; 22] = [0xB0, 0x14, 0xCC, 0x08, 0x0F, 0x1F, 0x00, 0x0C,
|
||||
0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x77, 0x55];
|
||||
let mut packet = UnsubackPacket::<2, 1>::new();
|
||||
let res = packet.decode(& mut BuffReader::new(&buffer, 22));
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(packet.fixed_header, PacketType::Unsuback.into());
|
||||
assert_eq!(packet.remain_len, 20);
|
||||
assert_eq!(packet.packet_identifier, 52232);
|
||||
assert_eq!(packet.property_len, 15);
|
||||
let prop = packet.properties.get(0);
|
||||
assert!(prop.is_some());
|
||||
assert_eq!(<&Property as Into<u8>>::into(prop.unwrap()), 0x1F);
|
||||
if let Property::ReasonString(u) = (*prop.unwrap()).clone() {
|
||||
assert_eq!(u.len, 12);
|
||||
assert_eq!(u.string, "reasonString");
|
||||
}
|
||||
assert_eq!(packet.reason_codes.len(), 2);
|
||||
let res1 = packet.reason_codes.get(0);
|
||||
assert!(res1.is_some());
|
||||
if let Some(r) = res1 {
|
||||
assert_eq!(*r, 0x77);
|
||||
}
|
||||
let res2 = packet.reason_codes.get(1);
|
||||
assert!(res2.is_some());
|
||||
if let Some(r) = res2 {
|
||||
assert_eq!(*r, 0x55);
|
||||
}
|
||||
}
|
61
src/tests/unit/packet/v5/unsubscription_packet_unit.rs
Normal file
61
src/tests/unit/packet/v5/unsubscription_packet_unit.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::mqtt_packet::Packet;
|
||||
use crate::packet::v5::packet_type::PacketType;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::packet::v5::publish_packet::QualityOfService::{QoS0, QoS1};
|
||||
use crate::packet::v5::subscription_packet::SubscriptionPacket;
|
||||
use crate::packet::v5::unsubscription_packet::UnsubscriptionPacket;
|
||||
use crate::utils::types::{EncodedString, StringPair};
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
let mut buffer: [u8; 40] = [0; 40];
|
||||
let mut packet = UnsubscriptionPacket::<2, 1>::new();
|
||||
packet.fixed_header = PacketType::Unsubscribe.into();
|
||||
packet.packet_identifier = 5432;
|
||||
let mut name = EncodedString::new();
|
||||
name.string = "haha";
|
||||
name.len = 4;
|
||||
let mut val = EncodedString::new();
|
||||
val.string = "hehe89";
|
||||
val.len = 6;
|
||||
let mut pair = StringPair::new();
|
||||
pair.name = name;
|
||||
pair.value = val;
|
||||
let mut props = Vec::<Property, 1>::new();
|
||||
props.push(Property::UserProperty(pair));
|
||||
packet.property_len = packet.add_properties(&props);
|
||||
packet.add_new_filter("test/topic", QoS0);
|
||||
packet.add_new_filter("hehe/#", QoS1);
|
||||
let res = packet.encode(& mut buffer, 40);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(res.unwrap(), 40);
|
||||
assert_eq!(buffer, [0xA0, 0x26, 0x15, 0x38, 0x0F, 0x26, 0x00, 0x04, 0x68, 0x61,
|
||||
0x68, 0x61, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x38, 0x39,
|
||||
0x00, 0x0A, 0x74, 0x65, 0x73, 0x74, 0x2F, 0x74, 0x6F, 0x70,
|
||||
0x69, 0x63, 0x00, 0x06, 0x68, 0x65, 0x68, 0x65, 0x2F, 0x23]);
|
||||
}
|
213
src/tests/unit/utils/buffer_reader_unit.rs
Normal file
213
src/tests/unit/utils/buffer_reader_unit.rs
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use core::str;
|
||||
|
||||
use log::info;
|
||||
use crate::utils::buffer_reader::BuffReader;
|
||||
use crate::utils::types::BufferError;
|
||||
|
||||
#[test]
|
||||
fn buffer_read_variable_byte() {
|
||||
static BUFFER: [u8; 5] = [0x82, 0x82, 0x03, 0x85, 0x84];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 5);
|
||||
let test_number = reader.read_variable_byte_int();
|
||||
assert!(test_number.is_ok());
|
||||
assert_eq!(reader.position, 3);
|
||||
assert_eq!(test_number.unwrap(), 49410);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_read_invalid_size() {
|
||||
static BUFFER: [u8; 2] = [0x82, 0x82];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 2);
|
||||
let test_number = reader.read_variable_byte_int();
|
||||
assert!(test_number.is_err());
|
||||
assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_smaller_var_int() {
|
||||
static BUFFER: [u8; 2] = [0x82, 0x02];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 2);
|
||||
let test_number = reader.read_variable_byte_int();
|
||||
assert!(test_number.is_ok());
|
||||
assert_eq!(reader.position, 2);
|
||||
assert_eq!(test_number.unwrap(), 258);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_complete_var_int() {
|
||||
static BUFFER: [u8; 4] = [0x81, 0x81, 0x81, 0x01];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 4);
|
||||
let test_number = reader.read_variable_byte_int();
|
||||
assert!(test_number.is_ok());
|
||||
assert_eq!(reader.position, 4);
|
||||
assert_eq!(test_number.unwrap(), 2113665);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_var_empty_buffer() {
|
||||
static BUFFER: [u8; 0] = [];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 0);
|
||||
let test_number = reader.read_variable_byte_int();
|
||||
assert!(test_number.is_err());
|
||||
assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u32() {
|
||||
static BUFFER: [u8; 4] = [0x00, 0x02, 0x5E, 0xC1];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 4);
|
||||
let test_number = reader.read_u32();
|
||||
assert!(test_number.is_ok());
|
||||
assert_eq!(test_number.unwrap(), 155329);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u32_oob() {
|
||||
static BUFFER: [u8; 3] = [0x00, 0x02, 0x5E];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 3);
|
||||
let test_number = reader.read_u32();
|
||||
assert!(test_number.is_err());
|
||||
assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u16() {
|
||||
static BUFFER: [u8; 2] = [0x48, 0x5F];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 2);
|
||||
let test_number = reader.read_u16();
|
||||
assert!(test_number.is_ok());
|
||||
assert_eq!(test_number.unwrap(), 18527);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u16_oob() {
|
||||
static BUFFER: [u8; 1] = [0x5E];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 1);
|
||||
let test_number = reader.read_u16();
|
||||
assert!(test_number.is_err());
|
||||
assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u8() {
|
||||
static BUFFER: [u8; 1] = [0xFD];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 1);
|
||||
let test_number = reader.read_u8();
|
||||
assert!(test_number.is_ok());
|
||||
assert_eq!(test_number.unwrap(), 253);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u8_oob() {
|
||||
static BUFFER: [u8; 0] = [];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 0);
|
||||
let test_number = reader.read_u8();
|
||||
assert!(test_number.is_err());
|
||||
assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_string() {
|
||||
static BUFFER: [u8; 6] = [0x00, 0x04, 0xF0, 0x9F, 0x92, 0x96];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 6);
|
||||
let test_string = reader.read_string();
|
||||
assert!(test_string.is_ok());
|
||||
let unw = test_string.unwrap();
|
||||
assert_eq!(unw.string, "💖");
|
||||
assert_eq!(unw.len, 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_string_utf8_wrong() {
|
||||
static BUFFER: [u8; 5] = [0x00, 0x03, 0xF0, 0x9F, 0x92];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 5);
|
||||
let test_string = reader.read_string();
|
||||
assert!(test_string.is_err());
|
||||
assert_eq!(test_string.unwrap_err(), BufferError::Utf8Error);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_string_oob() {
|
||||
static BUFFER: [u8; 5] = [0x00, 0x04, 0xF0, 0x9F, 0x92];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 5);
|
||||
let test_string = reader.read_string();
|
||||
assert!(test_string.is_err());
|
||||
assert_eq!(test_string.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_binary() {
|
||||
static BUFFER: [u8; 6] = [0x00, 0x04, 0xFF, 0xEE, 0xDD, 0xCC];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 6);
|
||||
let test_bin = reader.read_binary();
|
||||
assert!(test_bin.is_ok());
|
||||
let unw = test_bin.unwrap();
|
||||
assert_eq!(unw.bin, [0xFF, 0xEE, 0xDD, 0xCC]);
|
||||
assert_eq!(unw.len, 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_binary_oob() {
|
||||
static BUFFER: [u8; 5] = [0x00, 0x04, 0xFF, 0xEE, 0xDD];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 5);
|
||||
let test_bin = reader.read_binary();
|
||||
assert!(test_bin.is_err());
|
||||
assert_eq!(test_bin.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_string_pair() {
|
||||
static BUFFER: [u8; 11] = [0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E, 0x00, 0x03, 0xE2, 0x93, 0x87];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 11);
|
||||
let string_pair = reader.read_string_pair();
|
||||
assert!(string_pair.is_ok());
|
||||
let unw = string_pair.unwrap();
|
||||
assert_eq!(unw.name.string, "😎");
|
||||
assert_eq!(unw.name.len, 4);
|
||||
assert_eq!(unw.value.string, "Ⓡ");
|
||||
assert_eq!(unw.value.len, 3);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_read_string_pair_wrong_utf8() {
|
||||
static BUFFER: [u8; 11] = [0x00, 0x03, 0xF0, 0x9F, 0x92, 0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 11);
|
||||
let string_pair = reader.read_string_pair();
|
||||
assert!(string_pair.is_err());
|
||||
assert_eq!(string_pair.unwrap_err(), BufferError::Utf8Error)
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_string_pair_oob() {
|
||||
static BUFFER: [u8; 11] = [0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E, 0x00, 0x04, 0xE2, 0x93, 0x87];
|
||||
let mut reader: BuffReader = BuffReader::new(&BUFFER, 11);
|
||||
let string_pair = reader.read_string_pair();
|
||||
assert!(string_pair.is_err());
|
||||
assert_eq!(string_pair.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
360
src/tests/unit/utils/buffer_writer_unit.rs
Normal file
360
src/tests/unit/utils/buffer_writer_unit.rs
Normal file
|
@ -0,0 +1,360 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use heapless::Vec;
|
||||
use crate::packet::v5::property::Property;
|
||||
use crate::utils::buffer_writer::BuffWriter;
|
||||
use crate::utils::types::{BinaryData, BufferError, EncodedString, StringPair, TopicFilter};
|
||||
|
||||
#[test]
|
||||
fn buffer_write_ref() {
|
||||
static BUFFER: [u8; 5] = [0x82, 0x82, 0x03, 0x85, 0x84];
|
||||
let mut res_buffer: [u8; 5] = [0; 5];
|
||||
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 5);
|
||||
let test_write = writer.insert_ref(5, &BUFFER);
|
||||
assert!(test_write.is_ok());
|
||||
assert_eq!(writer.position, 5);
|
||||
assert_eq!(BUFFER, res_buffer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_ref_oob() {
|
||||
static BUFFER: [u8; 5] = [0x82, 0x82, 0x03, 0x85, 0x84];
|
||||
let mut res_buffer: [u8; 4] = [0; 4];
|
||||
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 4);
|
||||
let test_number = writer.insert_ref(5, &BUFFER);
|
||||
assert!(test_number.is_err());
|
||||
assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
assert_eq!(res_buffer, [0; 4])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_u8() {
|
||||
let mut res_buffer: [u8; 1] = [0; 1];
|
||||
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 1);
|
||||
let test_write = writer.write_u8(0xFA);
|
||||
assert!(test_write.is_ok());
|
||||
assert_eq!(writer.position, 1);
|
||||
assert_eq!(res_buffer, [0xFA]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_u8_oob() {
|
||||
let mut res_buffer: [u8; 0] = [];
|
||||
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 0);
|
||||
let test_number = writer.write_u8(0xFA);
|
||||
assert!(test_number.is_err());
|
||||
assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_u16() {
|
||||
let mut res_buffer: [u8; 2] = [0; 2];
|
||||
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 2);
|
||||
let test_write = writer.write_u16(0xFAED);
|
||||
assert!(test_write.is_ok());
|
||||
assert_eq!(writer.position, 2);
|
||||
assert_eq!(res_buffer, [0xFA, 0xED]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_u16_oob() {
|
||||
let mut res_buffer: [u8; 1] = [0; 1];
|
||||
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 1);
|
||||
let test_number = writer.write_u16(0xFAED);
|
||||
assert!(test_number.is_err());
|
||||
assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_u32() {
|
||||
let mut res_buffer: [u8; 4] = [0; 4];
|
||||
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 4);
|
||||
let test_write = writer.write_u32(0xFAEDCC09);
|
||||
assert!(test_write.is_ok());
|
||||
assert_eq!(writer.position, 4);
|
||||
assert_eq!(res_buffer, [0xFA, 0xED, 0xCC, 0x09]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_u32_oob() {
|
||||
let mut res_buffer: [u8; 3] = [0; 3];
|
||||
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 3);
|
||||
let test_number = writer.write_u32(0xFAEDCC08);
|
||||
assert!(test_number.is_err());
|
||||
assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_string() {
|
||||
let mut res_buffer: [u8; 6] = [0; 6];
|
||||
let mut string = EncodedString::new();
|
||||
string.string = "😎";
|
||||
string.len = 4;
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 6);
|
||||
let test_write = writer.write_string_ref(&string);
|
||||
assert!(test_write.is_ok());
|
||||
assert_eq!(writer.position, 6);
|
||||
assert_eq!(res_buffer, [0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E]);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn buffer_write_string_oob() {
|
||||
let mut res_buffer: [u8; 5] = [0; 5];
|
||||
let mut string = EncodedString::new();
|
||||
string.string = "😎";
|
||||
string.len = 4;
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 5);
|
||||
let test_write = writer.write_string_ref(&string);
|
||||
assert!(test_write.is_err());
|
||||
assert_eq!(test_write.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_bin() {
|
||||
let mut res_buffer: [u8; 6] = [0; 6];
|
||||
let mut bin = BinaryData::new();
|
||||
bin.bin = &[0xAB, 0xEF, 0x88, 0x43];
|
||||
bin.len = 4;
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 6);
|
||||
let test_write = writer.write_binary_ref(&bin);
|
||||
assert!(test_write.is_ok());
|
||||
assert_eq!(writer.position, 6);
|
||||
assert_eq!(res_buffer, [0x00, 0x04, 0xAB, 0xEF, 0x88, 0x43]);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn buffer_write_bin_oob() {
|
||||
let mut res_buffer: [u8; 6] = [0; 6];
|
||||
let mut bin = BinaryData::new();
|
||||
bin.bin = &[0xAB, 0xEF, 0x88, 0x43];
|
||||
bin.len = 4;
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 5);
|
||||
let test_write = writer.write_binary_ref(&bin);
|
||||
assert!(test_write.is_err());
|
||||
assert_eq!(test_write.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_string_pair() {
|
||||
let mut res_buffer: [u8; 12] = [0; 12];
|
||||
let mut name = EncodedString::new();
|
||||
name.string = "Name";
|
||||
name.len = 4;
|
||||
|
||||
let mut value = EncodedString::new();
|
||||
value.string = "😎";
|
||||
value.len = 4;
|
||||
let mut pair = StringPair::new();
|
||||
pair.name = name;
|
||||
pair.value = value;
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 12);
|
||||
let test_write = writer.write_string_pair_ref(&pair);
|
||||
assert!(test_write.is_ok());
|
||||
assert_eq!(writer.position, 12);
|
||||
assert_eq!(res_buffer, [0x00, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x04, 0xF0, 0x9F, 0x98, 0x8E]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_string_pair_oob() {
|
||||
let mut res_buffer: [u8; 12] = [0; 12];
|
||||
let mut name = EncodedString::new();
|
||||
name.string = "Name";
|
||||
name.len = 4;
|
||||
|
||||
let mut value = EncodedString::new();
|
||||
value.string = "😎";
|
||||
value.len = 4;
|
||||
let mut pair = StringPair::new();
|
||||
pair.name = name;
|
||||
pair.value = value;
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 10);
|
||||
let test_write = writer.write_string_pair_ref(&pair);
|
||||
assert!(test_write.is_err());
|
||||
assert_eq!(test_write.unwrap_err(), BufferError::InsufficientBufferSize)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_var_byte() {
|
||||
let mut res_buffer: [u8; 2] = [0; 2];
|
||||
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 2);
|
||||
let test_write = writer.write_variable_byte_int(512);
|
||||
assert!(test_write.is_ok());
|
||||
assert_eq!(writer.position, 2);
|
||||
assert_eq!(res_buffer, [0x80, 0x04]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_var_byte_oob() {
|
||||
let mut res_buffer: [u8; 2] = [0; 2];
|
||||
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 2);
|
||||
let test_number = writer.write_variable_byte_int(453123);
|
||||
assert!(test_number.is_err());
|
||||
assert_eq!(test_number.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
/*#[test]
|
||||
fn buffer_write_property() {
|
||||
let mut res_buffer: [u8; 7] = [0; 7];
|
||||
let mut topic = EncodedString::new();
|
||||
topic.string = "Name";
|
||||
topic.len = 4;
|
||||
let prop = Property::ResponseTopic(topic);
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 7);
|
||||
let test_write = writer.write_property(&prop);
|
||||
assert!(test_write.is_ok());
|
||||
assert_eq!(writer.position, 7);
|
||||
assert_eq!(res_buffer, [0x08, 0x00, 0x04, 0x4e, 0x61, 0x6d, 0x65]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_property_oob() {
|
||||
let mut res_buffer: [u8; 7] = [0; 7];
|
||||
let mut topic = EncodedString::new();
|
||||
topic.string = "Name";
|
||||
topic.len = 4;
|
||||
let prop = Property::ResponseTopic(topic);
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 4);
|
||||
let test_write = writer.write_property(&prop);
|
||||
assert!(test_write.is_err());
|
||||
assert_eq!(test_write.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}*/
|
||||
|
||||
#[test]
|
||||
fn buffer_write_properties() {
|
||||
let mut res_buffer: [u8; 13] = [0; 13];
|
||||
let mut topic = EncodedString::new();
|
||||
topic.string = "Name";
|
||||
topic.len = 4;
|
||||
let prop = Property::ResponseTopic(topic);
|
||||
let mut corr = BinaryData::new();
|
||||
corr.bin = &[0x12, 0x34, 0x56];
|
||||
corr.len = 3;
|
||||
let prop2 = Property::CorrelationData(corr);
|
||||
let mut properties = Vec::<Property, 2>::new();
|
||||
properties.push(prop);
|
||||
properties.push(prop2);
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 13);
|
||||
let test_write = writer.write_properties(&properties);
|
||||
assert!(test_write.is_ok());
|
||||
assert_eq!(writer.position, 13);
|
||||
assert_eq!(res_buffer, [0x08, 0x00, 0x04, 0x4e, 0x61, 0x6d, 0x65,
|
||||
0x09, 0x00, 0x03, 0x12, 0x34, 0x56]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_properties_oob() {
|
||||
let mut res_buffer: [u8; 10] = [0; 10];
|
||||
let mut topic = EncodedString::new();
|
||||
topic.string = "Name";
|
||||
topic.len = 4;
|
||||
let prop = Property::ResponseTopic(topic);
|
||||
let mut corr = BinaryData::new();
|
||||
corr.bin = &[0x12, 0x34, 0x56];
|
||||
corr.len = 3;
|
||||
let prop2 = Property::CorrelationData(corr);
|
||||
let mut properties = Vec::<Property, 2>::new();
|
||||
properties.push(prop);
|
||||
properties.push(prop2);
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 10);
|
||||
let test_write = writer.write_properties(&properties);
|
||||
assert!(test_write.is_err());
|
||||
assert_eq!(test_write.unwrap_err(), BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_filters() {
|
||||
let mut res_buffer: [u8; 15] = [0; 15];
|
||||
static STR1: &str = "test";
|
||||
static STR2: &str = "topic";
|
||||
let mut topic = EncodedString::new();
|
||||
topic.string = STR1;
|
||||
topic.len = 4;
|
||||
|
||||
let mut topic2 = EncodedString::new();
|
||||
topic2.string = STR2;
|
||||
topic2.len = 5;
|
||||
|
||||
let mut filter1 = TopicFilter::new();
|
||||
filter1.filter = topic;
|
||||
filter1.sub_options = 0xAE;
|
||||
|
||||
let mut filter2 = TopicFilter::new();
|
||||
filter2.filter = topic2;
|
||||
filter2.sub_options = 0x22;
|
||||
|
||||
|
||||
let mut filters = Vec::<TopicFilter, 2>::new();
|
||||
filters.push(filter1);
|
||||
filters.push(filter2);
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 15);
|
||||
let test_write = writer.write_topic_filters_ref(true, 2, &filters);
|
||||
assert!(test_write.is_ok());
|
||||
assert_eq!(writer.position, 15);
|
||||
assert_eq!(res_buffer, [0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0xAE,
|
||||
0x00, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x22]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_write_filters_oob() {
|
||||
let mut res_buffer: [u8; 15] = [0; 15];
|
||||
static STR1: &str = "test";
|
||||
static STR2: &str = "topic";
|
||||
let mut topic = EncodedString::new();
|
||||
topic.string = STR1;
|
||||
topic.len = 4;
|
||||
|
||||
let mut topic2 = EncodedString::new();
|
||||
topic2.string = STR2;
|
||||
topic2.len = 5;
|
||||
|
||||
let mut filter1 = TopicFilter::new();
|
||||
filter1.filter = topic;
|
||||
filter1.sub_options = 0xAE;
|
||||
|
||||
let mut filter2 = TopicFilter::new();
|
||||
filter2.filter = topic2;
|
||||
filter2.sub_options = 0x22;
|
||||
|
||||
|
||||
let mut filters = Vec::<TopicFilter, 2>::new();
|
||||
filters.push(filter1);
|
||||
filters.push(filter2);
|
||||
let mut writer: BuffWriter = BuffWriter::new(& mut res_buffer, 5);
|
||||
let test_write = writer.write_topic_filters_ref(true, 2, &filters);
|
||||
assert!(test_write.is_err());
|
||||
assert_eq!(test_write.unwrap_err(), BufferError::InsufficientBufferSize)
|
||||
}
|
26
src/tests/unit/utils/mod.rs
Normal file
26
src/tests/unit/utils/mod.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) [2022] [Ondrej Babec <ond.babec@gmail.com>]
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
pub mod buffer_reader_unit;
|
||||
pub mod buffer_writer_unit;
|
|
@ -1,9 +1,11 @@
|
|||
use alloc::format;
|
||||
use alloc::string::String;
|
||||
use core::future::Future;
|
||||
use core::time::Duration;
|
||||
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::time::sleep;
|
||||
|
||||
use crate::network::network_trait::Network;
|
||||
use crate::packet::v5::reason_codes::ReasonCode;
|
||||
|
@ -34,11 +36,17 @@ impl Network for TokioNetwork {
|
|||
where
|
||||
Self: 'm,
|
||||
= impl Future<Output = Result<(), ReasonCode>> + 'm;
|
||||
|
||||
type ReadFuture<'m>
|
||||
where
|
||||
Self: 'm,
|
||||
= impl Future<Output = Result<usize, ReasonCode>> + 'm;
|
||||
|
||||
type TimerFuture<'m>
|
||||
where
|
||||
Self: 'm,
|
||||
= impl Future<Output = ()>;
|
||||
|
||||
fn new(ip: [u8; 4], port: u16) -> Self {
|
||||
return Self {
|
||||
ip,
|
||||
|
@ -82,4 +90,11 @@ impl Network for TokioNetwork {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn count_down(&'m mut self, time_in_secs: u64) -> Self::TimerFuture<'m> {
|
||||
async move {
|
||||
return sleep(Duration::from_secs(time_in_secs))
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,22 +52,36 @@ impl<'a> BuffReader<'a> {
|
|||
/// Variable byte integer can be 1-4 Bytes long. Buffer reader takes all 4 Bytes at first and
|
||||
/// than check what is true length of varbyteint and increment cursor by that
|
||||
pub fn read_variable_byte_int(&mut self) -> Result<u32, BufferError> {
|
||||
let variable_byte_integer: [u8; 4] = [
|
||||
self.buffer[self.position],
|
||||
self.buffer[self.position + 1],
|
||||
self.buffer[self.position + 2],
|
||||
self.buffer[self.position + 3],
|
||||
];
|
||||
let mut variable_byte_integer: [u8; 4] = [0; 4];
|
||||
let mut len: usize = 1;
|
||||
// Everytime checking first bit of Byte which determines whenever there is continous Byte
|
||||
if variable_byte_integer[0] & 0x80 == 1 {
|
||||
len = len + 1;
|
||||
if variable_byte_integer[1] & 0x80 == 1 {
|
||||
len = len + 1;
|
||||
if variable_byte_integer[2] & 0x80 == 1 {
|
||||
len = len + 1;
|
||||
|
||||
// Everytime checking first bit of Byte which determines whenever there is continuous Byte
|
||||
let mut x = 0;
|
||||
loop {
|
||||
if x >= 4 {
|
||||
break;
|
||||
}
|
||||
if self.position + x >= self.len {
|
||||
return Err(BufferError::InsufficientBufferSize);
|
||||
}
|
||||
if self.buffer[self.position + x] & 0x80 != 0 {
|
||||
variable_byte_integer[x] = self.buffer[self.position + x];
|
||||
len = len + 1
|
||||
} else {
|
||||
variable_byte_integer[x] = self.buffer[self.position + x];
|
||||
x = x + 1;
|
||||
if x != 4 {
|
||||
loop {
|
||||
variable_byte_integer[x] = 0;
|
||||
x = x + 1;
|
||||
if x == 4 {
|
||||
break
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
x = x + 1;
|
||||
}
|
||||
self.increment_position(len);
|
||||
return VariableByteIntegerDecoder::decode(variable_byte_integer);
|
||||
|
@ -75,6 +89,9 @@ impl<'a> BuffReader<'a> {
|
|||
|
||||
/// Reading u32 from buffer as `Big endian`
|
||||
pub fn read_u32(&mut self) -> Result<u32, BufferError> {
|
||||
if self.position + 4 > self.len {
|
||||
return Err(BufferError::InsufficientBufferSize);
|
||||
}
|
||||
let (int_bytes, _rest) = self.buffer[self.position..].split_at(mem::size_of::<u32>());
|
||||
let ret: u32 = u32::from_be_bytes(int_bytes.try_into().unwrap());
|
||||
self.increment_position(4);
|
||||
|
@ -83,6 +100,9 @@ impl<'a> BuffReader<'a> {
|
|||
|
||||
/// Reading u16 from buffer as `Big endinan`
|
||||
pub fn read_u16(&mut self) -> Result<u16, BufferError> {
|
||||
if self.position + 2 > self.len {
|
||||
return Err(BufferError::InsufficientBufferSize);
|
||||
}
|
||||
let (int_bytes, _rest) = self.buffer[self.position..].split_at(mem::size_of::<u16>());
|
||||
let ret: u16 = u16::from_be_bytes(int_bytes.try_into().unwrap());
|
||||
self.increment_position(2);
|
||||
|
@ -91,6 +111,9 @@ impl<'a> BuffReader<'a> {
|
|||
|
||||
/// Reading one byte from buffer as `Big endian`
|
||||
pub fn read_u8(&mut self) -> Result<u8, BufferError> {
|
||||
if self.position >= self.len {
|
||||
return Err(BufferError::InsufficientBufferSize);
|
||||
}
|
||||
let ret: u8 = self.buffer[self.position];
|
||||
self.increment_position(1);
|
||||
return Ok(ret);
|
||||
|
@ -98,50 +121,47 @@ impl<'a> BuffReader<'a> {
|
|||
|
||||
/// Reading UTF-8 encoded string from buffer
|
||||
pub fn read_string(&mut self) -> Result<EncodedString<'a>, BufferError> {
|
||||
let len = self.read_u16();
|
||||
match len {
|
||||
Err(err) => return Err(err),
|
||||
_ => {}
|
||||
let len = self.read_u16() ? as usize;
|
||||
|
||||
if self.position + len - 1 >= self.len {
|
||||
return Err(BufferError::InsufficientBufferSize);
|
||||
}
|
||||
let len_res = len.unwrap();
|
||||
|
||||
let res_str =
|
||||
str::from_utf8(&(self.buffer[self.position..(self.position + len_res as usize)]));
|
||||
str::from_utf8(&(self.buffer[self.position..(self.position + len)]));
|
||||
if res_str.is_err() {
|
||||
log::error!("Could not parse utf-8 string");
|
||||
return Err(BufferError::Utf8Error);
|
||||
}
|
||||
self.increment_position(len_res as usize);
|
||||
self.increment_position(len);
|
||||
return Ok(EncodedString {
|
||||
string: res_str.unwrap(),
|
||||
len: len_res,
|
||||
len: len as u16,
|
||||
});
|
||||
}
|
||||
|
||||
/// Read Binary data from buffer
|
||||
pub fn read_binary(&mut self) -> Result<BinaryData<'a>, BufferError> {
|
||||
let len = self.read_u16()?;
|
||||
let len = self.read_u16() ?;
|
||||
|
||||
if self.position + len as usize - 1 >= self.len {
|
||||
return Err(BufferError::InsufficientBufferSize);
|
||||
}
|
||||
|
||||
let res_bin = &(self.buffer[self.position..(self.position + len as usize)]);
|
||||
return Ok(BinaryData {
|
||||
bin: res_bin,
|
||||
len: len,
|
||||
len,
|
||||
});
|
||||
}
|
||||
|
||||
/// Read string pair from buffer
|
||||
pub fn read_string_pair(&mut self) -> Result<StringPair<'a>, BufferError> {
|
||||
let name = self.read_string();
|
||||
match name {
|
||||
Err(err) => return Err(err),
|
||||
_ => log::debug!("[String pair] name not parsed"),
|
||||
}
|
||||
let value = self.read_string();
|
||||
match value {
|
||||
Err(err) => return Err(err),
|
||||
_ => log::debug!("[String pair] value not parsed"),
|
||||
}
|
||||
let name = self.read_string() ?;
|
||||
let value = self.read_string() ?;
|
||||
return Ok(StringPair {
|
||||
name: name.unwrap(),
|
||||
value: value.unwrap(),
|
||||
name,
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ impl<'a> BuffWriter<'a> {
|
|||
|
||||
pub fn insert_ref(&mut self, len: usize, array: &[u8]) -> Result<(), BufferError> {
|
||||
let mut x: usize = 0;
|
||||
if self.position + 3 >= self.len {
|
||||
if self.position + len > self.len {
|
||||
return Err(BufferError::InsufficientBufferSize);
|
||||
}
|
||||
if len != 0 {
|
||||
|
@ -91,45 +91,29 @@ impl<'a> BuffWriter<'a> {
|
|||
return self.insert_ref(str.len as usize, bytes);
|
||||
}
|
||||
|
||||
pub fn write_string(&mut self, str: EncodedString<'a>) -> Result<(), BufferError> {
|
||||
self.write_u16(str.len)?;
|
||||
let bytes = str.string.as_bytes();
|
||||
return self.insert_ref(str.len as usize, bytes);
|
||||
}
|
||||
|
||||
pub fn write_binary_ref(&mut self, bin: &BinaryData<'a>) -> Result<(), BufferError> {
|
||||
self.write_u16(bin.len)?;
|
||||
return self.insert_ref(bin.len as usize, bin.bin);
|
||||
}
|
||||
|
||||
pub fn write_binary(&mut self, bin: BinaryData<'a>) -> Result<(), BufferError> {
|
||||
self.write_u16(bin.len)?;
|
||||
return self.insert_ref(bin.len as usize, bin.bin);
|
||||
}
|
||||
|
||||
pub fn write_string_pair_ref(&mut self, str_pair: &StringPair<'a>) -> Result<(), BufferError> {
|
||||
self.write_string_ref(&str_pair.name)?;
|
||||
return self.write_string_ref(&str_pair.value);
|
||||
}
|
||||
|
||||
pub fn write_string_pair(&mut self, str_pair: StringPair<'a>) -> Result<(), BufferError> {
|
||||
self.write_string(str_pair.name)?;
|
||||
return self.write_string(str_pair.value);
|
||||
}
|
||||
|
||||
pub fn write_variable_byte_int(&mut self, int: u32) -> Result<(), BufferError> {
|
||||
let x: VariableByteInteger = VariableByteIntegerEncoder::encode(int)?;
|
||||
let len = VariableByteIntegerEncoder::len(x);
|
||||
return self.insert_ref(len, &x);
|
||||
}
|
||||
|
||||
pub fn encode_property(&mut self, property: &Property<'a>) -> Result<(), BufferError> {
|
||||
fn write_property(&mut self, property: &Property<'a>) -> Result<(), BufferError> {
|
||||
let x: u8 = property.into();
|
||||
self.write_u8(x)?;
|
||||
return property.encode(self);
|
||||
}
|
||||
|
||||
pub fn encode_properties<const LEN: usize>(
|
||||
pub fn write_properties<const LEN: usize>(
|
||||
&mut self,
|
||||
properties: &Vec<Property<'a>, LEN>,
|
||||
) -> Result<(), BufferError> {
|
||||
|
@ -138,7 +122,7 @@ impl<'a> BuffWriter<'a> {
|
|||
if len != 0 {
|
||||
loop {
|
||||
let prop: &Property = properties.get(i).unwrap_or(&Property::Reserved());
|
||||
self.encode_property(prop)?;
|
||||
self.write_property(prop)?;
|
||||
i = i + 1;
|
||||
if i == len {
|
||||
break;
|
||||
|
@ -148,7 +132,7 @@ impl<'a> BuffWriter<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn encode_topic_filter_ref(
|
||||
fn write_topic_filter_ref(
|
||||
&mut self,
|
||||
sub: bool,
|
||||
topic_filter: &TopicFilter<'a>,
|
||||
|
@ -160,7 +144,7 @@ impl<'a> BuffWriter<'a> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn encode_topic_filters_ref<const MAX: usize>(
|
||||
pub fn write_topic_filters_ref<const MAX: usize>(
|
||||
&mut self,
|
||||
sub: bool,
|
||||
len: usize,
|
||||
|
@ -169,7 +153,7 @@ impl<'a> BuffWriter<'a> {
|
|||
let mut i = 0;
|
||||
loop {
|
||||
let topic_filter: &TopicFilter<'a> = filters.get(i).unwrap();
|
||||
self.encode_topic_filter_ref(sub, topic_filter)?;
|
||||
self.write_topic_filter_ref(sub, topic_filter)?;
|
||||
i = i + 1;
|
||||
if i == len {
|
||||
break;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
use core::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(core::fmt::Debug, Clone)]
|
||||
#[derive(PartialEq)]
|
||||
pub enum BufferError {
|
||||
Utf8Error,
|
||||
InsufficientBufferSize,
|
||||
|
@ -65,6 +66,7 @@ impl EncodedString<'_> {
|
|||
pub fn new() -> Self {
|
||||
Self { string: "", len: 0 }
|
||||
}
|
||||
|
||||
/// Return length of string
|
||||
pub fn len(&self) -> u16 {
|
||||
return self.len + 2;
|
||||
|
@ -89,13 +91,19 @@ impl BinaryData<'_> {
|
|||
}
|
||||
|
||||
/// String pair struct represents `String pair` in MQTTv5 (2 UTF-8 encoded strings name-value)
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StringPair<'a> {
|
||||
pub name: EncodedString<'a>,
|
||||
pub value: EncodedString<'a>,
|
||||
}
|
||||
|
||||
impl StringPair<'_> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
name: EncodedString::new(),
|
||||
value: EncodedString::new()
|
||||
}
|
||||
}
|
||||
/// Returns length which is equal to sum of the lenghts of UTF-8 encoded strings in pair
|
||||
pub fn len(&self) -> u16 {
|
||||
let ln = self.name.len() + self.value.len();
|
||||
|
|
Loading…
Reference in New Issue
Block a user