info.rs (3819B)
1 use super::RadrootsRuntime; 2 use chrono::Utc; 3 use radroots_net_core::net; 4 use serde::Serialize; 5 6 #[derive(Debug, Clone, Serialize, Default, uniffi::Record)] 7 pub struct NetBuildInfo { 8 pub crate_name: String, 9 pub crate_version: String, 10 pub rustc: Option<String>, 11 pub profile: Option<String>, 12 pub git_sha: Option<String>, 13 pub build_time_unix: Option<u64>, 14 } 15 16 impl From<&net::BuildInfo> for NetBuildInfo { 17 fn from(b: &net::BuildInfo) -> Self { 18 Self { 19 crate_name: b.crate_name.to_string(), 20 crate_version: b.crate_version.to_string(), 21 rustc: b.rustc.map(|s| s.to_string()), 22 profile: b.profile.map(|s| s.to_string()), 23 git_sha: b.git_sha.map(|s| s.to_string()), 24 build_time_unix: b.build_time_unix, 25 } 26 } 27 } 28 29 #[derive(Debug, Clone, Serialize, uniffi::Record)] 30 pub struct AppInfo { 31 pub build: NetBuildInfo, 32 pub started_unix_ms: i64, 33 pub uptime_millis: i64, 34 pub shutting_down: bool, 35 pub platform: Option<super::app_info::AppInfoPlatform>, 36 } 37 38 #[derive(Debug, Clone, Serialize, uniffi::Record)] 39 pub struct RuntimeInfo { 40 pub app: AppInfo, 41 pub net: NetBuildInfo, 42 } 43 44 pub fn gather_runtime_info(runtime: &RadrootsRuntime) -> RuntimeInfo { 45 let now_ms = Utc::now().timestamp_millis(); 46 let app_info = AppInfo { 47 build: app_build_info(), 48 started_unix_ms: runtime.started_unix_ms, 49 uptime_millis: now_ms - runtime.started_unix_ms, 50 shutting_down: runtime 51 .shutting_down 52 .load(std::sync::atomic::Ordering::SeqCst), 53 platform: runtime.platform_app.read().ok().and_then(|g| (*g).clone()), 54 }; 55 56 let net_info = match runtime.net.lock() { 57 Ok(guard) => NetBuildInfo::from(&guard.info.build), 58 Err(_) => NetBuildInfo::default(), 59 }; 60 61 RuntimeInfo { 62 app: app_info, 63 net: net_info, 64 } 65 } 66 67 pub fn app_build_info() -> NetBuildInfo { 68 NetBuildInfo { 69 crate_name: env!("CARGO_PKG_NAME").to_string(), 70 crate_version: env!("CARGO_PKG_VERSION").to_string(), 71 rustc: env_opt_to_owned(option_env!("RUSTC_VERSION")), 72 profile: env_opt_to_owned(option_env!("PROFILE")), 73 git_sha: env_opt_to_owned(option_env!("GIT_HASH")), 74 build_time_unix: env_opt_to_u64(option_env!("BUILD_TIME_UNIX")), 75 } 76 } 77 78 fn env_opt_to_owned(value: Option<&str>) -> Option<String> { 79 value.map(str::to_owned) 80 } 81 82 fn env_opt_to_u64(value: Option<&str>) -> Option<u64> { 83 value.map(str::parse::<u64>).and_then(Result::ok) 84 } 85 86 #[cfg(test)] 87 mod tests { 88 use super::NetBuildInfo; 89 use radroots_net_core::net; 90 91 #[test] 92 fn net_build_info_from_copies_optional_fields() { 93 let source = net::BuildInfo { 94 crate_name: "radroots-net-core", 95 crate_version: "1.2.3", 96 rustc: Some("rustc 1.92.0"), 97 profile: Some("debug"), 98 git_sha: Some("abc123"), 99 build_time_unix: Some(1_700_000_000), 100 }; 101 102 let out = NetBuildInfo::from(&source); 103 assert_eq!(out.crate_name, "radroots-net-core"); 104 assert_eq!(out.crate_version, "1.2.3"); 105 assert_eq!(out.rustc.as_deref(), Some("rustc 1.92.0")); 106 assert_eq!(out.profile.as_deref(), Some("debug")); 107 assert_eq!(out.git_sha.as_deref(), Some("abc123")); 108 assert_eq!(out.build_time_unix, Some(1_700_000_000)); 109 } 110 111 #[test] 112 fn env_opt_helpers_cover_some_none_and_parse_failure() { 113 assert_eq!(super::env_opt_to_owned(Some("abc")).as_deref(), Some("abc")); 114 assert_eq!(super::env_opt_to_owned(None), None); 115 assert_eq!(super::env_opt_to_u64(Some("123")), Some(123)); 116 assert_eq!(super::env_opt_to_u64(Some("abc")), None); 117 assert_eq!(super::env_opt_to_u64(None), None); 118 } 119 }