use thiserror::Error;
#[derive(Debug, Error, PartialEq)]
pub enum Ipv4Error {
#[error("Invalid IPv4 packet length: expected at least {expected} bytes, got {actual} bytes")]
InvalidLength {
expected: usize,
actual: usize,
},
#[error("Invalid IP version: expected 4, got {0}")]
InvalidVersion(u8),
#[error("Invalid header length: {0} bytes (must be between 20-60 bytes and a multiple of 4)")]
InvalidHeaderLength(usize),
#[error("Invalid total length: expected {expected} bytes (header: {min_header_len} + data: {}), but got {actual} bytes", expected - min_header_len)]
InvalidTotalLength {
expected: usize,
actual: usize,
min_header_len: usize,
},
#[error("Invalid header checksum: expected {expected:#06x}, got {actual:#06x}")]
InvalidChecksum {
expected: u16,
actual: u16,
},
#[error("TTL expired: {0}")]
TtlExpired(u8),
#[error("Unsupported protocol: {0}")]
UnsupportedProtocol(u8),
#[error("Invalid IP option: {0}")]
InvalidOption(String),
#[error("Fragmented packet - requires reassembly (offset: {0}, more fragments: {1})")]
FragmentedPacket(u16, bool),
#[error("Packet too large: {0} bytes (maximum allowed: {1} bytes)")]
PacketTooLarge(usize, usize),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_messages() {
let err = Ipv4Error::InvalidLength {
expected: 20,
actual: 10,
};
assert_eq!(
err.to_string(),
"Invalid IPv4 packet length: expected at least 20 bytes, got 10 bytes"
);
let err = Ipv4Error::InvalidVersion(6);
assert_eq!(err.to_string(), "Invalid IP version: expected 4, got 6");
let err = Ipv4Error::InvalidHeaderLength(19);
assert_eq!(
err.to_string(),
"Invalid header length: 19 bytes (must be between 20-60 bytes and a multiple of 4)"
);
let err = Ipv4Error::InvalidTotalLength {
expected: 100,
actual: 50,
min_header_len: 20,
};
assert_eq!(
err.to_string(),
"Invalid total length: expected 100 bytes (header: 20 + data: 80), but got 50 bytes"
);
let err = Ipv4Error::InvalidChecksum {
expected: 0x1234,
actual: 0x5678,
};
assert_eq!(
err.to_string(),
"Invalid header checksum: expected 0x1234, got 0x5678"
);
let err = Ipv4Error::TtlExpired(0);
assert_eq!(err.to_string(), "TTL expired: 0");
let err = Ipv4Error::UnsupportedProtocol(123);
assert_eq!(err.to_string(), "Unsupported protocol: 123");
let err = Ipv4Error::InvalidOption("invalid option".to_string());
assert_eq!(err.to_string(), "Invalid IP option: invalid option");
let err = Ipv4Error::FragmentedPacket(1480, true);
assert_eq!(
err.to_string(),
"Fragmented packet - requires reassembly (offset: 1480, more fragments: true)"
);
let err = Ipv4Error::PacketTooLarge(65536, 1500);
assert_eq!(
err.to_string(),
"Packet too large: 65536 bytes (maximum allowed: 1500 bytes)"
);
}
}