use std::fmt;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum ConnectivityState {
Unknown,
None,
Portal,
Limited,
Full,
}
impl ConnectivityState {
#[must_use]
pub fn is_usable_for_internet(self) -> bool {
matches!(self, Self::Full)
}
#[must_use]
pub fn is_captive(self) -> bool {
matches!(self, Self::Portal)
}
}
impl From<u32> for ConnectivityState {
fn from(v: u32) -> Self {
match v {
0 => Self::Unknown,
1 => Self::None,
2 => Self::Portal,
3 => Self::Limited,
4 => Self::Full,
_ => Self::Unknown,
}
}
}
impl From<ConnectivityState> for u32 {
fn from(s: ConnectivityState) -> u32 {
match s {
ConnectivityState::Unknown => 0,
ConnectivityState::None => 1,
ConnectivityState::Portal => 2,
ConnectivityState::Limited => 3,
ConnectivityState::Full => 4,
}
}
}
impl fmt::Display for ConnectivityState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Unknown => write!(f, "unknown"),
Self::None => write!(f, "none"),
Self::Portal => write!(f, "portal"),
Self::Limited => write!(f, "limited"),
Self::Full => write!(f, "full"),
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct ConnectivityReport {
pub state: ConnectivityState,
pub check_enabled: bool,
pub check_uri: Option<String>,
pub captive_portal_url: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn round_trip_all() {
for code in 0..=4 {
let s = ConnectivityState::from(code);
assert_eq!(u32::from(s), code);
}
}
#[test]
fn out_of_range_maps_to_unknown() {
assert_eq!(ConnectivityState::from(99), ConnectivityState::Unknown);
}
#[test]
fn is_captive() {
assert!(ConnectivityState::Portal.is_captive());
assert!(!ConnectivityState::Full.is_captive());
assert!(!ConnectivityState::None.is_captive());
}
#[test]
fn is_usable() {
assert!(ConnectivityState::Full.is_usable_for_internet());
assert!(!ConnectivityState::Portal.is_usable_for_internet());
assert!(!ConnectivityState::Limited.is_usable_for_internet());
assert!(!ConnectivityState::Unknown.is_usable_for_internet());
}
}