bnto_core/metadata/
install_hints.rs1use serde::{Deserialize, Serialize};
9#[cfg(feature = "ts")]
10use ts_rs::TS;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum HostPlatform {
15 MacOs,
16 Linux,
17 Windows,
18}
19
20impl HostPlatform {
21 pub const fn current() -> Option<Self> {
24 if cfg!(target_os = "macos") {
25 Some(Self::MacOs)
26 } else if cfg!(target_os = "linux") {
27 Some(Self::Linux)
28 } else if cfg!(windows) {
29 Some(Self::Windows)
30 } else {
31 None
32 }
33 }
34}
35
36#[cfg_attr(feature = "ts", derive(TS))]
39#[cfg_attr(
40 feature = "ts",
41 ts(
42 export,
43 export_to = "../../../../packages/@bnto/nodes/src/generated/definitionTypes/"
44 )
45)]
46#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
47pub struct InstallHints {
48 #[serde(default, skip_serializing_if = "String::is_empty")]
50 pub macos: String,
51 #[serde(default, skip_serializing_if = "String::is_empty")]
53 pub linux: String,
54 #[serde(default, skip_serializing_if = "String::is_empty")]
56 pub windows: String,
57}
58
59impl InstallHints {
60 pub fn for_platform(&self, platform: HostPlatform) -> Option<&str> {
62 let hint = match platform {
63 HostPlatform::MacOs => &self.macos,
64 HostPlatform::Linux => &self.linux,
65 HostPlatform::Windows => &self.windows,
66 };
67 (!hint.is_empty()).then_some(hint.as_str())
68 }
69
70 pub fn is_empty(&self) -> bool {
72 self.macos.is_empty() && self.linux.is_empty() && self.windows.is_empty()
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 fn hints() -> InstallHints {
81 InstallHints {
82 macos: "brew install yt-dlp".to_string(),
83 linux: String::new(),
84 windows: "winget install yt-dlp.yt-dlp".to_string(),
85 }
86 }
87
88 #[test]
89 fn for_platform_returns_matching_hint() {
90 let h = hints();
91 assert_eq!(
92 h.for_platform(HostPlatform::MacOs),
93 Some("brew install yt-dlp")
94 );
95 assert_eq!(
96 h.for_platform(HostPlatform::Windows),
97 Some("winget install yt-dlp.yt-dlp")
98 );
99 }
100
101 #[test]
102 fn for_platform_returns_none_when_unset() {
103 assert_eq!(hints().for_platform(HostPlatform::Linux), None);
104 }
105
106 #[test]
107 fn is_empty_only_when_no_platform_set() {
108 assert!(InstallHints::default().is_empty());
109 assert!(!hints().is_empty());
110 }
111
112 #[test]
113 fn deserializes_partial_object() {
114 let h: InstallHints = serde_json::from_str(r#"{ "windows": "winget install x" }"#).unwrap();
115 assert_eq!(h.windows, "winget install x");
116 assert!(h.macos.is_empty() && h.linux.is_empty());
117 }
118
119 #[test]
120 fn serializes_without_empty_platforms() {
121 let json = serde_json::to_string(&hints()).unwrap();
122 assert!(!json.contains("linux"), "empty platforms omitted: {json}");
123 }
124
125 #[test]
126 fn current_matches_compile_target() {
127 let expected = if cfg!(target_os = "macos") {
128 Some(HostPlatform::MacOs)
129 } else if cfg!(target_os = "linux") {
130 Some(HostPlatform::Linux)
131 } else if cfg!(windows) {
132 Some(HostPlatform::Windows)
133 } else {
134 None
135 };
136 assert_eq!(HostPlatform::current(), expected);
137 }
138}