yggdrasil/lib/abi/src/net/link.rs

162 lines
4.4 KiB
Rust

//! Types for handling network interface link state information
use core::fmt;
use abi_serde::{
des::{DeserializeError, Deserializer},
ser::Serializer,
Deserialize, Serialize,
};
use crate::primitive_enum;
primitive_enum! {
/// Defines an Ethernet link speed
pub enum EthernetSpeed: u8 {
/// 1Gbps link
Speed1000 = 3,
/// 100Mbps link
Speed100 = 2,
/// 10Mbps link
Speed10 = 1,
/// Link speed not available/unknown
Unknown = 0,
}
[with_serde]
}
primitive_enum! {
/// Defines whether an Ethernet link is capable of transmiting data both ways simultaneously
pub enum Duplex: u32 {
/// Half-duplex mode
Half = 1,
/// Full-duplex mode
Full = 2,
/// Duplex mode information not available/unknown
Unknown = 0,
}
[with_serde]
}
/// Represents the state of an Ethernet link
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum EthernetLinkState {
/// Link is up, fields indicate the link configuration
Up(EthernetSpeed, Duplex),
/// Link is down
Down,
}
/// Represents the state of network interface's link
#[derive(Debug, Clone, PartialEq)]
pub enum LinkState {
/// Ethernet link state
Ethernet(EthernetLinkState),
/// Any other device, just indicates whether the link is up or down
Other {
/// If `true`, the link is up
up: bool,
},
}
impl Serialize for EthernetLinkState {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
match self {
Self::Up(speed, duplex) => {
serializer.write_u8(0x01)?;
speed.serialize(serializer)?;
duplex.serialize(serializer)
}
Self::Down => serializer.write_u8(0x00),
}
}
}
impl Serialize for LinkState {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
match self {
Self::Ethernet(state) => {
serializer.write_u8(0xEE)?;
state.serialize(serializer)
}
Self::Other { up } => {
serializer.write_u8(0xFF)?;
up.serialize(serializer)
}
}
}
}
impl<'de> Deserialize<'de> for EthernetLinkState {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
match deserializer.read_u8()? {
0x01 => {
let speed = EthernetSpeed::deserialize(deserializer)?;
let duplex = Duplex::deserialize(deserializer)?;
Ok(Self::Up(speed, duplex))
}
0x00 => Ok(Self::Down),
_ => Err(D::Error::INVALID_ENUM_VARIANT),
}
}
}
impl<'de> Deserialize<'de> for LinkState {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
match deserializer.read_u8()? {
0xEE => EthernetLinkState::deserialize(deserializer).map(Self::Ethernet),
0xFF => {
let up = bool::deserialize(deserializer)?;
Ok(Self::Other { up })
}
_ => Err(D::Error::INVALID_ENUM_VARIANT),
}
}
}
impl fmt::Display for EthernetSpeed {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let text = match self {
Self::Speed10 => "10Mbps",
Self::Speed100 => "100Mbps",
Self::Speed1000 => "1Gbps",
Self::Unknown => "N/A",
};
f.write_str(text)
}
}
impl fmt::Display for Duplex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let text = match self {
Self::Half => "half-duplex",
Self::Full => "full-duplex",
Self::Unknown => "N/A duplex mode",
};
f.write_str(text)
}
}
impl fmt::Display for EthernetLinkState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Up(speed, duplex) => {
write!(f, "up, speed {speed}, {duplex}")
}
Self::Down => {
write!(f, "down")
}
}
}
}
impl fmt::Display for LinkState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Other { up: true } => write!(f, "up"),
Self::Other { up: false } => write!(f, "down"),
Self::Ethernet(ethernet) => fmt::Display::fmt(ethernet, f),
}
}
}