use thiserror::Error;
use crate::common::enums::ProtocolVersion;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PduState {
Uninitialized,
HeaderValid,
BodyValid,
Complete,
}
#[derive(Error, Debug)]
pub enum DISError {
#[error("Invalid PDU header: {reason}")]
InvalidHeader {
reason: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync>>,
},
#[error("PDU deserialization error: {msg}")]
DeserializationError {
msg: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync>>,
},
#[error("PDU serialization error: {msg}")]
SerializationError {
msg: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync>>,
},
#[error("Invalid PDU state transition: {current_state:?} -> {target_state:?}")]
InvalidStateTransition {
current_state: PduState,
target_state: PduState,
},
#[error("Protocol version mismatch: expected {expected:?}, got {got:?}")]
ProtocolVersionMismatch {
expected: ProtocolVersion,
got: ProtocolVersion,
},
#[error("Invalid field value: {field} = {value}, {reason}")]
InvalidFieldValue {
field: String,
value: String,
reason: String,
},
#[error("Buffer underflow: tried to read {attempted} bytes, but only {available} bytes remain")]
BufferUnderflow { attempted: usize, available: usize },
#[error("Network error: {0}")]
NetworkError(#[from] std::io::Error),
#[error("PDU size exceeds maximum allowed: {size} > {max_size}")]
PduSizeExceeded { size: usize, max_size: usize },
}
impl DISError {
pub fn invalid_header<S: Into<String>>(
reason: S,
source: Option<Box<dyn std::error::Error + Send + Sync>>,
) -> Self {
Self::InvalidHeader {
reason: reason.into(),
source,
}
}
pub fn deserialization_error<S: Into<String>>(
msg: S,
source: Option<Box<dyn std::error::Error + Send + Sync>>,
) -> Self {
Self::DeserializationError {
msg: msg.into(),
source,
}
}
pub fn serialization_error<S: Into<String>>(
msg: S,
source: Option<Box<dyn std::error::Error + Send + Sync>>,
) -> Self {
Self::SerializationError {
msg: msg.into(),
source,
}
}
pub fn invalid_field<S: Into<String>>(field: S, value: S, reason: S) -> Self {
Self::InvalidFieldValue {
field: field.into(),
value: value.into(),
reason: reason.into(),
}
}
#[must_use]
pub const fn buffer_underflow(attempted: usize, available: usize) -> Self {
Self::BufferUnderflow {
attempted,
available,
}
}
#[must_use]
pub const fn pdu_size_exceeded(size: usize, max_size: usize) -> Self {
Self::PduSizeExceeded { size, max_size }
}
}
pub type DISResult<T> = Result<T, DISError>;