use crate::{utils::*, MqttError};
const MQTT_V4_PROTOCOL: &[u8] = &[0u8, 4, b'M', b'Q', b'T', b'T', 4];
const MQTT_V5_PROTOCOL: &[u8] = &[0u8, 4, b'M', b'Q', b'T', b'T', 5];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Protocol {
V4,
V5,
}
impl Protocol {
pub fn new(name: &str, level: u8) -> Result<Self, MqttError> {
match (name, level) {
("MQTT", 4) => Ok(Protocol::V4),
("MQTT", 5) => Ok(Protocol::V5),
(_, level) => Err(MqttError::InvalidProtocol(level)),
}
}
pub fn read(buf: &[u8], offset: &mut usize) -> Result<Self, MqttError> {
let protocol_name = read_str(buf, offset)?;
let protocol_level = buf[*offset];
*offset += 1;
Protocol::new(protocol_name, protocol_level)
}
pub fn write(&self, buf: &mut [u8], offset: &mut usize) -> usize {
match self {
Protocol::V4 => {
for &byte in MQTT_V4_PROTOCOL {
write_u8(buf, offset, byte);
}
MQTT_V4_PROTOCOL.len()
}
Protocol::V5 => {
for &byte in MQTT_V5_PROTOCOL {
write_u8(buf, offset, byte);
}
MQTT_V5_PROTOCOL.len()
}
}
}
}
#[cfg(test)]
mod tests {
use super::{Protocol, MQTT_V4_PROTOCOL, MQTT_V5_PROTOCOL};
fn sample_bytes_mqtt5() -> Vec<u8> {
vec![
0x10, 0x1f, 0x00, 0x04, 0x4d, 0x51, 0x54, 0x54, 0x05, ]
}
#[test]
fn mqtt_v5_read() {
let protocol = Protocol::read(&sample_bytes_mqtt5(), &mut 2).unwrap();
assert_eq!(protocol, Protocol::V5)
}
#[test]
fn mqtt_v5_read_write() {
let mut buf = [0u8; 7];
let protocol = Protocol::read(&sample_bytes_mqtt5(), &mut 2).unwrap();
protocol.write(&mut buf, &mut 0);
assert_eq!(buf, MQTT_V5_PROTOCOL);
}
fn sample_bytes_mqtt4() -> Vec<u8> {
vec![
0x10, 0x1f, 0x00, 0x04, 0x4d, 0x51, 0x54, 0x54, 0x04, ]
}
#[test]
fn mqtt_v4_read() {
let protocol = Protocol::read(&sample_bytes_mqtt4(), &mut 2).unwrap();
assert_eq!(protocol, Protocol::V4)
}
#[test]
fn mqtt_v4_read_write() {
let mut buf = [0u8; 7];
let protocol = Protocol::read(&sample_bytes_mqtt4(), &mut 2).unwrap();
protocol.write(&mut buf, &mut 0);
assert_eq!(buf, MQTT_V4_PROTOCOL);
}
}