embedded-mqtt 0.1.0

no_std encoder/decoder for MQTT 3.1.1 protocol packets for embedded devices.
Documentation
use core::{
	convert::TryFrom,
	result::Result,
};

use crate::{
	fixed_header::{PacketFlags, PublishFlags},
	codec::{self, Encodable},
	status::Status,
	error::{DecodeError, EncodeError},
	qos,
};

use super::{PacketId, HeaderDecode};

#[derive(Debug)]
pub struct Publish<'a> {
	topic_name: &'a str,
	packet_identifier: Option<PacketId>,
}

impl<'a> Publish<'a> {
	pub fn new(topic_name: &'a str, packet_identifier: Option<PacketId>) -> Self {
		Self {
			topic_name,
			packet_identifier,
		}
	}

	pub fn topic_name(&self) -> &'a str {
		self.topic_name
	}

	pub fn packet_identifier(&self) -> Option<PacketId> {
		self.packet_identifier
	}
}

impl<'a> HeaderDecode<'a> for Publish<'a> {
	fn decode(flags: PacketFlags, bytes: &'a [u8]) -> Result<Status<(usize, Self)>, DecodeError> {
		let flags = PublishFlags::try_from(flags)?;

		let offset = 0;
		let (offset, topic_name) = read!(codec::string::parse_string, bytes, offset);

		let (offset, packet_identifier) = if flags.qos()? != qos::QoS::AtMostOnce {
			let (offset, packet_identifier) = read!(codec::values::parse_u16, bytes, offset);
			(offset, Some(packet_identifier))
		} else {
			(offset, None)
		};

		Ok(Status::Complete((offset, Self {
			topic_name,
			packet_identifier
		})))
	}
}

impl<'a> Encodable for Publish<'a> {
	fn encoded_len(&self) -> usize {
		self.topic_name.encoded_len() + self.packet_identifier.map(|_| 2).unwrap_or(0)
	}

	fn encode(&self, bytes: &mut [u8]) -> Result<usize, EncodeError> {
		let offset = 0;
		let offset = {
			let o = self.topic_name.encode(&mut bytes[offset..])?;
			offset + o
		};
		let offset = if let Some(packet_identifier) = self.packet_identifier {
			let o = codec::values::encode_u16(packet_identifier, &mut bytes[offset..])?;
			offset + o
		} else {
			offset
		};
		Ok(offset)
	}
}

#[cfg(test)]
mod tests {
	use super::*;

	#[test]
	fn encode() {
		let header = Publish {
			topic_name: "a/b",
			packet_identifier: Some(1),
		};

		assert_eq!(7, header.encoded_len());

		let mut buf = [0u8; 7];
		let res = header.encode(&mut buf[..]);
		assert_eq!(res, Ok(7));

		assert_eq!(buf, [
			0b0000_0000,
			0b0000_0011,
			0x61,
			0x2f,
			0x62,
			0b0000_0000,
			0b0000_0001,
		]);
	}
}