use crate::models::common::IpAddress;
use serde::Deserialize;
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Default)]
pub enum ClientType {
#[serde(alias = "WIRED")]
Wired,
#[serde(alias = "WIRELESS")]
Wireless,
#[serde(other)]
#[default]
Unknown,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Default)]
pub enum AccessType {
#[serde(alias = "DEFAULT")]
#[default]
Default,
#[serde(alias = "BLOCKED")]
Blocked,
#[serde(alias = "ALLOWED")]
Allowed,
#[serde(alias = "GUEST")]
Guest,
#[serde(other)]
Unknown,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Default)]
pub struct ClientAccess {
#[serde(default, rename = "type")]
pub access_type: AccessType,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
pub struct Client {
pub id: String,
#[serde(default, rename = "type")]
pub client_type: ClientType,
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub connected_at: Option<String>,
#[serde(default)]
pub ip_address: Option<IpAddress>,
#[serde(default)]
pub access: Option<ClientAccess>,
#[serde(default)]
pub uplink_device_id: Option<String>,
}
impl Client {
pub fn is_wireless(&self) -> bool {
self.client_type == ClientType::Wireless
}
pub fn is_wired(&self) -> bool {
self.client_type == ClientType::Wired
}
pub fn is_connected(&self) -> bool {
self.connected_at.is_some()
}
pub fn is_blocked(&self) -> bool {
self.access
.as_ref()
.map(|a| a.access_type == AccessType::Blocked)
.unwrap_or(false)
}
pub fn is_guest(&self) -> bool {
self.access
.as_ref()
.map(|a| a.access_type == AccessType::Guest)
.unwrap_or(false)
}
pub fn device_id(&self) -> Option<&str> {
self.uplink_device_id.as_deref()
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_client_with_uplink_device_id() {
let json_data = json!({
"id": "client-123",
"type": "WIRELESS",
"name": "iPhone",
"connectedAt": "2024-01-01T12:00:00Z",
"ipAddress": "192.168.1.100",
"uplinkDeviceId": "device-456"
});
let client: Client = serde_json::from_value(json_data).unwrap();
assert_eq!(client.id, "client-123");
assert_eq!(client.client_type, ClientType::Wireless);
assert_eq!(client.uplink_device_id, Some("device-456".to_string()));
assert_eq!(client.device_id(), Some("device-456"));
assert!(client.is_wireless());
assert!(!client.is_wired());
}
#[test]
fn test_client_without_uplink_device_id() {
let json_data = json!({
"id": "client-789",
"type": "WIRED"
});
let client: Client = serde_json::from_value(json_data).unwrap();
assert_eq!(client.id, "client-789");
assert!(client.uplink_device_id.is_none());
assert_eq!(client.device_id(), None);
assert!(client.is_wired());
}
#[test]
fn test_guest_client() {
let json_data = json!({
"id": "guest-client",
"type": "WIRELESS",
"access": {
"type": "GUEST"
}
});
let client: Client = serde_json::from_value(json_data).unwrap();
assert!(client.is_guest());
assert!(!client.is_blocked());
}
#[test]
fn test_blocked_client() {
let json_data = json!({
"id": "blocked-client",
"type": "WIRELESS",
"access": {
"type": "BLOCKED"
}
});
let client: Client = serde_json::from_value(json_data).unwrap();
assert!(client.is_blocked());
assert!(!client.is_guest());
}
#[test]
fn test_access_type_deserialization() {
let default: AccessType = serde_json::from_str("\"DEFAULT\"").unwrap();
let blocked: AccessType = serde_json::from_str("\"BLOCKED\"").unwrap();
let allowed: AccessType = serde_json::from_str("\"ALLOWED\"").unwrap();
let guest: AccessType = serde_json::from_str("\"GUEST\"").unwrap();
let unknown: AccessType = serde_json::from_str("\"SOMETHING_ELSE\"").unwrap();
assert_eq!(default, AccessType::Default);
assert_eq!(blocked, AccessType::Blocked);
assert_eq!(allowed, AccessType::Allowed);
assert_eq!(guest, AccessType::Guest);
assert_eq!(unknown, AccessType::Unknown);
}
#[test]
fn test_is_connected() {
let connected = Client {
id: "client-1".to_string(),
connected_at: Some("2024-01-01T12:00:00Z".to_string()),
..Default::default()
};
assert!(connected.is_connected());
let disconnected = Client {
id: "client-2".to_string(),
connected_at: None,
..Default::default()
};
assert!(!disconnected.is_connected());
}
}