#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum WifiSecurity {
#[default]
Wpa,
Wep,
None,
}
impl WifiSecurity {
fn token(self) -> &'static str {
match self {
WifiSecurity::Wpa => "WPA",
WifiSecurity::Wep => "WEP",
WifiSecurity::None => "nopass",
}
}
}
fn escape(value: &str) -> String {
let mut out = String::with_capacity(value.len());
for ch in value.chars() {
if matches!(ch, '\\' | ';' | ',' | ':' | '"') {
out.push('\\');
}
out.push(ch);
}
out
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct WifiNetwork {
ssid: String,
password: Option<String>,
security: WifiSecurity,
hidden: bool,
}
impl WifiNetwork {
#[must_use]
pub fn new(ssid: impl Into<String>) -> Self {
WifiNetwork {
ssid: ssid.into(),
..Default::default()
}
}
#[must_use]
pub fn security(mut self, security: WifiSecurity) -> Self {
self.security = security;
self
}
#[must_use]
pub fn password(mut self, password: impl Into<String>) -> Self {
self.password = Some(password.into());
self
}
#[must_use]
pub fn hidden(mut self, hidden: bool) -> Self {
self.hidden = hidden;
self
}
#[must_use]
pub fn to_qr_string(&self) -> String {
let mut s = format!("WIFI:T:{};S:{};", self.security.token(), escape(&self.ssid));
if self.security != WifiSecurity::None {
if let Some(password) = &self.password {
s.push_str(&format!("P:{};", escape(password)));
}
}
if self.hidden {
s.push_str("H:true;");
}
s.push(';');
s
}
}
impl core::fmt::Display for WifiNetwork {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(&self.to_qr_string())
}
}