use crate::error::Result;
use crate::packet::{FixedHeader, MqttPacket, PacketType};
use crate::prelude::{format, Vec};
use bebytes::BeBytes;
use bytes::{Buf, BufMut};
#[derive(Debug, Clone, Copy, PartialEq, Eq, BeBytes)]
pub struct PingRespPacket {
#[bebytes(big_endian)]
fixed_header: u16, }
impl PingRespPacket {
pub const FIXED_HEADER: u16 = 0xD000; }
impl Default for PingRespPacket {
fn default() -> Self {
Self {
fixed_header: Self::FIXED_HEADER,
}
}
}
impl MqttPacket for PingRespPacket {
fn packet_type(&self) -> PacketType {
PacketType::PingResp
}
fn encode_body<B: BufMut>(&self, _buf: &mut B) -> Result<()> {
Ok(())
}
fn decode_body<B: Buf>(_buf: &mut B, _fixed_header: &FixedHeader) -> Result<Self> {
Ok(Self::default())
}
}
impl PingRespPacket {
#[must_use]
pub fn encode_complete(&self) -> Vec<u8> {
self.to_be_bytes()
}
pub fn decode_complete(data: &[u8]) -> Result<Self> {
let (packet, _consumed) = Self::try_from_be_bytes(data).map_err(|e| {
crate::error::MqttError::MalformedPacket(format!("Invalid PINGRESP packet: {e}"))
})?;
if packet.fixed_header != Self::FIXED_HEADER {
return Err(crate::error::MqttError::MalformedPacket(format!(
"Invalid PINGRESP packet: expected 0x{:04X}, got 0x{:04X}",
Self::FIXED_HEADER,
packet.fixed_header
)));
}
Ok(packet)
}
}
#[cfg(test)]
mod tests {
use super::*;
use bytes::BytesMut;
#[cfg(test)]
mod property_tests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn prop_pingresp_encode_decode_round_trip(_data in any::<u32>()) {
let packet = PingRespPacket::default();
let bytes = packet.encode_complete();
let decoded = PingRespPacket::decode_complete(&bytes).unwrap();
prop_assert_eq!(bytes, vec![0xD0, 0x00]);
prop_assert_eq!(decoded.packet_type(), PacketType::PingResp);
prop_assert_eq!(packet, decoded);
}
#[test]
fn prop_pingresp_consistent_encoding(_data in any::<u16>()) {
let packet1 = PingRespPacket::default();
let packet2 = PingRespPacket::default();
prop_assert_eq!(packet1.encode_complete(), packet2.encode_complete());
prop_assert_eq!(packet1, packet2);
}
}
}
#[test]
fn test_pingresp_bebytes_encode_decode() {
let packet = PingRespPacket::default();
let bytes = packet.encode_complete();
assert_eq!(bytes.len(), 2);
assert_eq!(bytes[0], 0xD0); assert_eq!(bytes[1], 0x00);
let decoded = PingRespPacket::decode_complete(&bytes).unwrap();
assert_eq!(decoded, packet);
}
#[test]
fn test_pingresp_mqtt_packet_interface() {
let packet = PingRespPacket::default();
let mut buf = BytesMut::new();
packet.encode(&mut buf).unwrap();
assert_eq!(buf.len(), 2); assert_eq!(buf[0], 0xD0); assert_eq!(buf[1], 0x00);
let fixed_header = FixedHeader::decode(&mut buf).unwrap();
assert_eq!(fixed_header.packet_type, PacketType::PingResp);
assert_eq!(fixed_header.remaining_length, 0);
let decoded = PingRespPacket::decode_body(&mut buf, &fixed_header).unwrap();
assert_eq!(decoded, packet);
}
#[test]
fn test_pingresp_malformed_data() {
let result = PingRespPacket::decode_complete(&[0xD0]);
assert!(result.is_err());
let result = PingRespPacket::decode_complete(&[0xC0, 0x00]);
assert!(result.is_err());
}
}