use bytes::{Buf, BufMut};
use tokio::io::AsyncReadExt;
use crate::packets::{
QoS,
error::{DeserializeError, SerializeError},
mqtt_trait::{MqttAsyncRead, MqttAsyncWrite, MqttRead, MqttWrite},
};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct ConnectFlags {
pub clean_start: bool,
pub will_flag: bool,
pub will_qos: QoS,
pub will_retain: bool,
pub password: bool,
pub username: bool,
}
impl ConnectFlags {
pub fn from_u8(value: u8) -> Result<Self, DeserializeError> {
Ok(Self {
clean_start: ((value & 0b00000010) >> 1) != 0,
will_flag: ((value & 0b00000100) >> 2) != 0,
will_qos: QoS::from_u8((value & 0b00011000) >> 3)?,
will_retain: ((value & 0b00100000) >> 5) != 0,
password: ((value & 0b01000000) >> 6) != 0,
username: ((value & 0b10000000) >> 7) != 0,
})
}
pub fn into_u8(&self) -> Result<u8, SerializeError> {
let byte = ((self.clean_start as u8) << 1)
| ((self.will_flag as u8) << 2)
| (self.will_qos.into_u8() << 3)
| ((self.will_retain as u8) << 5)
| ((self.password as u8) << 6)
| ((self.username as u8) << 7);
Ok(byte)
}
}
impl Default for ConnectFlags {
fn default() -> Self {
Self {
clean_start: false,
will_flag: false,
will_qos: QoS::AtMostOnce,
will_retain: false,
password: false,
username: false,
}
}
}
impl MqttRead for ConnectFlags {
fn read(buf: &mut bytes::Bytes) -> Result<Self, DeserializeError> {
if buf.is_empty() {
return Err(DeserializeError::InsufficientData(std::any::type_name::<Self>(), 0, 1));
}
let byte = buf.get_u8();
ConnectFlags::from_u8(byte)
}
}
impl<S> MqttAsyncRead<S> for ConnectFlags
where
S: tokio::io::AsyncRead + Unpin,
{
async fn async_read(stream: &mut S) -> Result<(Self, usize), crate::packets::error::ReadError> {
let byte = stream.read_u8().await?;
Ok((ConnectFlags::from_u8(byte)?, 1))
}
}
impl MqttWrite for ConnectFlags {
fn write(&self, buf: &mut bytes::BytesMut) -> Result<(), crate::packets::error::SerializeError> {
buf.put_u8(self.into_u8()?);
Ok(())
}
}
impl<S> MqttAsyncWrite<S> for ConnectFlags
where
S: tokio::io::AsyncWrite + Unpin,
{
async fn async_write(&self, stream: &mut S) -> Result<usize, crate::packets::error::WriteError> {
use tokio::io::AsyncWriteExt;
let byte = self.into_u8()?;
stream.write_u8(byte).await?;
Ok(1)
}
}