use crate::error::{CrafterError, Result};
pub(crate) const DSCP_SHIFT: u8 = 2;
const DSCP_MAX: u8 = 0x3f;
pub(crate) const ECN_MASK: u8 = 0x03;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dscp(u8);
impl Dscp {
pub const fn new(value: u8) -> Result<Self> {
if value <= DSCP_MAX {
Ok(Self(value))
} else {
Err(CrafterError::invalid_field_value(
"ipv4.dscp",
"DSCP must fit in six bits",
))
}
}
pub(crate) const fn from_u6(value: u8) -> Self {
Self(value)
}
pub const fn from_ds_field(value: u8) -> Self {
Self(value >> DSCP_SHIFT)
}
pub const fn value(self) -> u8 {
self.0
}
pub const fn default_forwarding() -> Self {
Self::cs0()
}
pub const fn cs0() -> Self {
Self::from_u6(0)
}
pub const fn cs1() -> Self {
Self::from_u6(8)
}
pub const fn cs2() -> Self {
Self::from_u6(16)
}
pub const fn cs3() -> Self {
Self::from_u6(24)
}
pub const fn cs4() -> Self {
Self::from_u6(32)
}
pub const fn cs5() -> Self {
Self::from_u6(40)
}
pub const fn cs6() -> Self {
Self::from_u6(48)
}
pub const fn cs7() -> Self {
Self::from_u6(56)
}
pub const fn class_selector(selector: u8) -> Result<Self> {
if selector <= 7 {
Ok(Self(selector << 3))
} else {
Err(CrafterError::invalid_field_value(
"ip.dscp.class_selector",
"Class Selector must be in the range 0..=7",
))
}
}
pub const fn ef() -> Self {
Self::from_u6(46)
}
}
impl Default for Dscp {
fn default() -> Self {
Self::default_forwarding()
}
}
impl TryFrom<u8> for Dscp {
type Error = CrafterError;
fn try_from(value: u8) -> Result<Self> {
Self::new(value)
}
}
impl From<Dscp> for u8 {
fn from(value: Dscp) -> Self {
value.value()
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum Ecn {
#[default]
NotEct = 0,
Ect1 = 1,
Ect0 = 2,
Ce = 3,
}
impl Ecn {
pub const fn new(value: u8) -> Result<Self> {
match value {
0 => Ok(Self::NotEct),
1 => Ok(Self::Ect1),
2 => Ok(Self::Ect0),
3 => Ok(Self::Ce),
_ => Err(CrafterError::invalid_field_value(
"ipv4.ecn",
"ECN must fit in two bits",
)),
}
}
pub(crate) const fn from_u2(value: u8) -> Self {
match value & ECN_MASK {
0 => Self::NotEct,
1 => Self::Ect1,
2 => Self::Ect0,
_ => Self::Ce,
}
}
pub const fn from_ds_field(value: u8) -> Self {
Self::from_u2(value)
}
pub const fn value(self) -> u8 {
self as u8
}
pub const fn not_ect() -> Self {
Self::NotEct
}
pub const fn ect1() -> Self {
Self::Ect1
}
pub const fn ect0() -> Self {
Self::Ect0
}
pub const fn capable_0() -> Self {
Self::Ect0
}
pub const fn capable_1() -> Self {
Self::Ect1
}
pub const fn ce() -> Self {
Self::Ce
}
}
impl TryFrom<u8> for Ecn {
type Error = CrafterError;
fn try_from(value: u8) -> Result<Self> {
Self::new(value)
}
}
impl From<Ecn> for u8 {
fn from(value: Ecn) -> Self {
value.value()
}
}