use std::fmt::{Display, Formatter};
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct Device {
pub path: String,
pub interface: String,
pub identity: DeviceIdentity,
pub device_type: DeviceType,
pub state: DeviceState,
pub managed: Option<bool>,
pub driver: Option<String>,
pub ip4_address: Option<String>,
pub ip6_address: Option<String>,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DeviceIdentity {
pub permanent_mac: String,
pub current_mac: String,
}
impl DeviceIdentity {
#[must_use]
pub fn new(permanent_mac: String, current_mac: String) -> Self {
Self {
permanent_mac,
current_mac,
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum DeviceType {
Ethernet,
Wifi,
WifiP2P,
Loopback,
Bluetooth,
Other(u32),
}
impl DeviceType {
#[must_use]
pub fn supports_scanning(&self) -> bool {
match self {
Self::Wifi | Self::WifiP2P => true,
Self::Other(code) => crate::types::device_type_registry::supports_scanning(*code),
_ => false,
}
}
#[must_use]
pub fn requires_specific_object(&self) -> bool {
match self {
Self::Wifi | Self::WifiP2P => true,
Self::Other(code) => {
crate::types::device_type_registry::requires_specific_object(*code)
}
_ => false,
}
}
#[must_use]
pub fn has_global_enabled_state(&self) -> bool {
match self {
Self::Wifi => true,
Self::Other(code) => {
crate::types::device_type_registry::has_global_enabled_state(*code)
}
_ => false,
}
}
#[must_use]
pub fn connection_type_str(&self) -> &'static str {
match self {
Self::Ethernet => "802-3-ethernet",
Self::Wifi => "802-11-wireless",
Self::WifiP2P => "wifi-p2p",
Self::Loopback => "loopback",
Self::Bluetooth => "bluetooth",
Self::Other(code) => {
crate::types::device_type_registry::connection_type_for_code(*code)
.unwrap_or("generic")
}
}
}
#[must_use]
pub fn to_code(&self) -> u32 {
match self {
Self::Ethernet => 1,
Self::Wifi => 2,
Self::WifiP2P => 30,
Self::Loopback => 32,
Self::Bluetooth => 6,
Self::Other(code) => *code,
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum DeviceState {
Unmanaged,
Unavailable,
Disconnected,
Prepare,
Config,
NeedAuth,
IpConfig,
IpCheck,
Secondaries,
Activated,
Deactivating,
Failed,
Other(u32),
}
impl DeviceState {
#[must_use]
pub fn is_transitional(&self) -> bool {
matches!(
self,
Self::Prepare
| Self::Config
| Self::NeedAuth
| Self::IpConfig
| Self::IpCheck
| Self::Secondaries
| Self::Deactivating
)
}
}
impl Device {
#[must_use]
pub fn is_wired(&self) -> bool {
matches!(self.device_type, DeviceType::Ethernet)
}
#[must_use]
pub fn is_wireless(&self) -> bool {
matches!(self.device_type, DeviceType::Wifi)
}
#[must_use]
pub fn is_bluetooth(&self) -> bool {
matches!(self.device_type, DeviceType::Bluetooth)
}
}
impl Display for Device {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{} ({}) [{}]",
self.interface, self.device_type, self.state
)
}
}
impl From<u32> for DeviceType {
fn from(value: u32) -> Self {
match value {
1 => DeviceType::Ethernet,
2 => DeviceType::Wifi,
5 => DeviceType::Bluetooth,
30 => DeviceType::WifiP2P,
32 => DeviceType::Loopback,
v => DeviceType::Other(v),
}
}
}
impl From<u32> for DeviceState {
fn from(value: u32) -> Self {
match value {
10 => Self::Unmanaged,
20 => Self::Unavailable,
30 => Self::Disconnected,
40 => Self::Prepare,
50 => Self::Config,
60 => Self::NeedAuth,
70 => Self::IpConfig,
80 => Self::IpCheck,
90 => Self::Secondaries,
100 => Self::Activated,
110 => Self::Deactivating,
120 => Self::Failed,
v => Self::Other(v),
}
}
}
impl Display for DeviceType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
DeviceType::Ethernet => write!(f, "Ethernet"),
DeviceType::Wifi => write!(f, "Wi-Fi"),
DeviceType::WifiP2P => write!(f, "Wi-Fi P2P"),
DeviceType::Loopback => write!(f, "Loopback"),
DeviceType::Bluetooth => write!(f, "Bluetooth"),
DeviceType::Other(v) => write!(
f,
"{}",
crate::types::device_type_registry::display_name_for_code(*v)
),
}
}
}
impl Display for DeviceState {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Unmanaged => write!(f, "Unmanaged"),
Self::Unavailable => write!(f, "Unavailable"),
Self::Disconnected => write!(f, "Disconnected"),
Self::Prepare => write!(f, "Preparing"),
Self::Config => write!(f, "Configuring"),
Self::NeedAuth => write!(f, "NeedAuth"),
Self::IpConfig => write!(f, "IpConfig"),
Self::IpCheck => write!(f, "IpCheck"),
Self::Secondaries => write!(f, "Secondaries"),
Self::Activated => write!(f, "Activated"),
Self::Deactivating => write!(f, "Deactivating"),
Self::Failed => write!(f, "Failed"),
Self::Other(v) => write!(f, "Other({v})"),
}
}
}