iwconf-win 0.1.2

A colorful, iwconfig-style WLAN CLI for Windows, backed by the native WLAN API (no netsh required).
//! Safe, platform-neutral WLAN model. The unsafe FFI against the native
//! Windows WLAN API (`wlanapi.dll`) lives in [`native`] and is only
//! compiled `cfg(windows)`. Everything in this module is just data +
//! glue so the CLI/display layers never touch raw WLAN structs.

#[cfg(windows)]
pub mod native;

#[cfg(windows)]
pub mod adapters;

use std::fmt;

use serde::Serialize;

/// One physical/virtual wireless adapter as WLAN AutoConfig sees it.
#[derive(Debug, Clone, Serialize)]
pub struct Interface {
    pub guid: String,
    pub name: String,
    pub description: String,
    pub state: InterfaceState,
    pub connection: Option<ConnectionInfo>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum InterfaceState {
    NotReady,
    Connected,
    AdHocNetworkFormed,
    Disconnecting,
    Disconnected,
    Associating,
    Discovering,
    Authenticating,
    Unknown,
}

impl fmt::Display for InterfaceState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            InterfaceState::NotReady => "not ready",
            InterfaceState::Connected => "connected",
            InterfaceState::AdHocNetworkFormed => "ad-hoc formed",
            InterfaceState::Disconnecting => "disconnecting",
            InterfaceState::Disconnected => "disconnected",
            InterfaceState::Associating => "associating",
            InterfaceState::Discovering => "discovering",
            InterfaceState::Authenticating => "authenticating",
            InterfaceState::Unknown => "unknown",
        };
        f.write_str(s)
    }
}

/// Details about the network an interface is currently associated with —
/// the rough equivalent of what `netsh wlan show interface` prints.
#[derive(Debug, Clone, Serialize)]
pub struct ConnectionInfo {
    pub ssid: String,
    pub bssid: String,
    pub network_type: String,
    pub radio_type: String,
    pub authentication: String,
    pub cipher: String,
    pub connection_mode: String,
    pub channel: Option<u32>,
    pub band_ghz: Option<f32>,
    pub rx_rate_mbps: Option<u32>,
    pub tx_rate_mbps: Option<u32>,
    /// 0-100, as WLAN AutoConfig reports it (already normalized from RSSI).
    pub signal_quality: Option<u8>,
    pub profile_name: Option<String>,
}

/// One SSID from a scan result, possibly with several BSSes folded in
/// (Windows groups scan results by SSID, same as `netsh wlan show networks`).
#[derive(Debug, Clone, Serialize)]
pub struct NetworkInfo {
    pub ssid: String,
    pub network_type: String,
    pub authentication: String,
    pub encryption: String,
    pub signal_quality: u8,
    pub connectable: bool,
    pub already_connected: bool,
    pub profile_name: Option<String>,
}

/// Result of a connect attempt, reported back for the CLI to render.
/// `Failed` is reserved for a hard failure signal distinct from a plain
/// timeout (`native::connect` doesn't produce it yet — it currently
/// surfaces hard failures as `Err` — but the CLI's match arm already
/// handles it so wiring it up later doesn't touch call sites).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(dead_code)]
pub enum ConnectOutcome {
    Connected,
    TimedOut,
    Failed,
}