use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ClientInfo {
pub id: String,
pub name: String,
pub platform: String,
pub version: String,
pub os: String,
pub os_version: String,
pub language: String,
pub time_zone: String,
pub user_agent: String,
pub debug: bool,
}
impl ClientInfo {
pub fn new() -> Self {
let rust_version = rustc_version::version()
.map(|v| v.to_string())
.unwrap_or_else(|_| "unknown".to_string());
let os = std::env::consts::OS;
let os_version = os_info::get().version().to_string();
let id = format!("Rust/{} ({})", rust_version, os);
ClientInfo {
id: id.clone(),
name: "Rust Client".to_string(),
platform: "rust".to_string(),
version: env!("CARGO_PKG_VERSION").to_string(),
os: os.to_string(),
os_version,
language: std::env::var("LANG").unwrap_or_else(|_| "en-US".to_string()),
time_zone: chrono::Local::now().offset().to_string(),
user_agent: id,
debug: cfg!(debug_assertions),
}
}
}
impl Default for ClientInfo {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_client_info_creation() {
let info = ClientInfo::new();
assert_eq!(info.platform, "rust");
assert_eq!(info.name, "Rust Client");
assert!(!info.version.is_empty());
assert!(!info.os.is_empty());
assert!(!info.id.is_empty());
assert!(info.id.starts_with("Rust/"));
}
#[test]
fn test_client_info_debug_flag() {
let info = ClientInfo::new();
assert!(info.debug);
}
#[test]
fn test_client_info_serialization() {
let info = ClientInfo::new();
let json = serde_json::to_value(&info).unwrap();
assert!(json.get("id").is_some());
assert!(json.get("name").is_some());
assert!(json.get("platform").is_some());
assert!(json.get("osVersion").is_some());
assert!(json.get("timeZone").is_some());
assert!(json.get("userAgent").is_some());
}
}