#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Header {
pub protocol_version: ProtocolVersion,
pub pdu_size: PduSize,
pub pdu_type: PduType,
pub message_count: MessageCount,
}
impl Header {
pub const SIZE: usize = 9;
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum ProtocolVersion {
V1 = 1,
}
#[derive(Debug, thiserror::Error)]
#[error("invalid protocol version {0}")]
pub struct InvalidProtocolVersion(u16);
impl TryFrom<u16> for ProtocolVersion {
type Error = InvalidProtocolVersion;
fn try_from(value: u16) -> Result<Self, Self::Error> {
match value {
1 => Ok(ProtocolVersion::V1),
_ => Err(InvalidProtocolVersion(value)),
}
}
}
impl From<ProtocolVersion> for u16 {
fn from(value: ProtocolVersion) -> Self {
value as u16
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct PduSize(u32);
impl From<u32> for PduSize {
fn from(value: u32) -> Self {
PduSize(value)
}
}
impl From<PduSize> for u32 {
fn from(PduSize(value): PduSize) -> Self {
value
}
}
impl PduSize {
pub fn size_excluding_header(&self) -> Option<usize> {
(self.0 as usize).checked_sub(Header::SIZE)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct MessageCount(u16);
impl MessageCount {
pub fn is_valid_for_pdu_type(&self, pdu_type: PduType) -> bool {
match pdu_type {
PduType::KeepAlive => self.0 == 1,
_ => true,
}
}
}
impl From<MessageCount> for u16 {
fn from(MessageCount(value): MessageCount) -> Self {
value
}
}
#[derive(Debug, thiserror::Error)]
#[error("invalid message count {0}")]
pub struct InvalidMessageCount(pub u16);
impl TryFrom<u16> for MessageCount {
type Error = InvalidMessageCount;
fn try_from(value: u16) -> Result<Self, Self::Error> {
if value > 0 {
Ok(MessageCount(value))
} else {
Err(InvalidMessageCount(value))
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum PduType {
Command = 0,
CommandResponseRequired = 1,
Notification1 = 2,
Response = 3,
KeepAlive = 4,
Notification2 = 5,
}
impl PduType {
pub const ALL: [PduType; 6] = [
PduType::Command,
PduType::CommandResponseRequired,
PduType::Notification1,
PduType::Response,
PduType::KeepAlive,
PduType::Notification2,
];
}
#[derive(Debug, thiserror::Error)]
#[error("invalid pdu type {0}")]
pub struct InvalidPduType(u8);
impl TryFrom<u8> for PduType {
type Error = InvalidPduType;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(PduType::Command),
1 => Ok(PduType::CommandResponseRequired),
2 => Ok(PduType::Notification1),
3 => Ok(PduType::Response),
4 => Ok(PduType::KeepAlive),
5 => Ok(PduType::Notification2),
_ => Err(InvalidPduType(value)),
}
}
}
impl From<PduType> for u8 {
fn from(value: PduType) -> Self {
value as u8
}
}