use core::error;
use core::fmt::{Debug, Display, Formatter};
use crate::error::{
InvalidChecksumError, LengthExceedsAvailableSpaceError, NotEnoughHeadroomError,
UnexpectedBufferEndError,
};
use crate::typed_protocol_headers::UnrecognizedInternetProtocolNumberError;
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum ParseIpv4Error {
UnexpectedBufferEnd(UnexpectedBufferEndError),
VersionHeaderValueNotFour,
IhlHeaderValueTooSmall {
ihl: usize,
},
PacketShorterThanTotalLengthHeaderValue {
total_length_header: usize,
actual_packet_length: usize,
},
TotalLengthHeaderValueSmallerThanIhlHeaderValue {
total_length_header: usize,
ihl_header_in_bytes: usize,
},
PacketShorterThanIhlHeaderValue {
ihl_header_in_bytes: usize,
actual_packet_length: usize,
},
UnrecognizedInternetProtocolNumber(UnrecognizedInternetProtocolNumberError),
InvalidChecksum(InvalidChecksumError),
}
impl From<UnrecognizedInternetProtocolNumberError> for ParseIpv4Error {
#[inline]
fn from(value: UnrecognizedInternetProtocolNumberError) -> Self {
Self::UnrecognizedInternetProtocolNumber(value)
}
}
impl From<UnexpectedBufferEndError> for ParseIpv4Error {
#[inline]
fn from(value: UnexpectedBufferEndError) -> Self {
Self::UnexpectedBufferEnd(value)
}
}
impl From<LengthExceedsAvailableSpaceError> for ParseIpv4Error {
#[inline]
fn from(value: LengthExceedsAvailableSpaceError) -> Self {
Self::UnexpectedBufferEnd(UnexpectedBufferEndError {
expected_length: value.required_space,
actual_length: value.available_space,
})
}
}
impl From<InvalidChecksumError> for ParseIpv4Error {
#[inline]
fn from(value: InvalidChecksumError) -> Self {
Self::InvalidChecksum(value)
}
}
impl Display for ParseIpv4Error {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Self::VersionHeaderValueNotFour => {
write!(f, "Version header is not 4")
}
Self::IhlHeaderValueTooSmall { ihl } => {
write!(
f,
"IHL header value invalid, expected to be between 5 and 15 (inclusive): {ihl}"
)
}
Self::PacketShorterThanTotalLengthHeaderValue {
total_length_header: total_length,
actual_packet_length: actual_length,
} => {
write!(
f,
"Total length does not match actual length, total length: {total_length} bytes - actual length: {actual_length} bytes"
)
}
Self::TotalLengthHeaderValueSmallerThanIhlHeaderValue {
total_length_header,
ihl_header_in_bytes,
} => {
write!(
f,
"Total length expected to be the same or larger than header length (IHL), total was: {total_length_header} bytes header was: {ihl_header_in_bytes} bytes"
)
}
Self::UnrecognizedInternetProtocolNumber(err) => {
write!(f, "{err}")
}
Self::UnexpectedBufferEnd(err) => {
write!(f, "{err}")
}
Self::InvalidChecksum(err) => {
write!(f, "{err}")
}
Self::PacketShorterThanIhlHeaderValue {
ihl_header_in_bytes,
actual_packet_length,
} => {
write!(
f,
"Packet length expected to be larger than IHL header length, packet length was: {actual_packet_length} bytes, IHL header was: {ihl_header_in_bytes} bytes"
)
}
}
}
}
impl error::Error for ParseIpv4Error {}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum SetTotalLengthError {
SmallerThanIhl,
LengthExceedsAvailableSpace(LengthExceedsAvailableSpaceError),
CannotCutUpperLayerHeader,
}
impl Display for SetTotalLengthError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Self::SmallerThanIhl => {
write!(f, "Provided value is smaller than IHL header value")
}
Self::CannotCutUpperLayerHeader => {
write!(
f,
"Provided length would cut off already parsed upper layer"
)
}
Self::LengthExceedsAvailableSpace(err) => {
write!(f, "{err}")
}
}
}
}
impl From<LengthExceedsAvailableSpaceError> for SetTotalLengthError {
#[inline]
fn from(value: LengthExceedsAvailableSpaceError) -> Self {
Self::LengthExceedsAvailableSpace(value)
}
}
impl error::Error for SetTotalLengthError {}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum SetIhlError {
InvalidIhl {
ihl: usize,
},
NotEnoughHeadroom(NotEnoughHeadroomError),
}
impl Display for SetIhlError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Self::InvalidIhl { ihl } => {
write!(
f,
"IHL header value invalid, expected to be between 5 and 20 (inclusive): {ihl}"
)
}
Self::NotEnoughHeadroom(err) => {
write!(f, "{err}")
}
}
}
}
impl From<NotEnoughHeadroomError> for SetIhlError {
#[inline]
fn from(value: NotEnoughHeadroomError) -> Self {
Self::NotEnoughHeadroom(value)
}
}
impl error::Error for SetIhlError {}