use serde::{Deserialize, Serialize};
#[cfg(feature = "ts")]
use ts_rs::TS;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HostPlatform {
MacOs,
Linux,
Windows,
}
impl HostPlatform {
pub const fn current() -> Option<Self> {
if cfg!(target_os = "macos") {
Some(Self::MacOs)
} else if cfg!(target_os = "linux") {
Some(Self::Linux)
} else if cfg!(windows) {
Some(Self::Windows)
} else {
None
}
}
}
#[cfg_attr(feature = "ts", derive(TS))]
#[cfg_attr(
feature = "ts",
ts(
export,
export_to = "../../../../packages/@bnto/nodes/src/generated/definitionTypes/"
)
)]
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
pub struct InstallHints {
#[serde(default, skip_serializing_if = "String::is_empty")]
pub macos: String,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub linux: String,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub windows: String,
}
impl InstallHints {
pub fn for_platform(&self, platform: HostPlatform) -> Option<&str> {
let hint = match platform {
HostPlatform::MacOs => &self.macos,
HostPlatform::Linux => &self.linux,
HostPlatform::Windows => &self.windows,
};
(!hint.is_empty()).then_some(hint.as_str())
}
pub fn is_empty(&self) -> bool {
self.macos.is_empty() && self.linux.is_empty() && self.windows.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn hints() -> InstallHints {
InstallHints {
macos: "brew install yt-dlp".to_string(),
linux: String::new(),
windows: "winget install yt-dlp.yt-dlp".to_string(),
}
}
#[test]
fn for_platform_returns_matching_hint() {
let h = hints();
assert_eq!(
h.for_platform(HostPlatform::MacOs),
Some("brew install yt-dlp")
);
assert_eq!(
h.for_platform(HostPlatform::Windows),
Some("winget install yt-dlp.yt-dlp")
);
}
#[test]
fn for_platform_returns_none_when_unset() {
assert_eq!(hints().for_platform(HostPlatform::Linux), None);
}
#[test]
fn is_empty_only_when_no_platform_set() {
assert!(InstallHints::default().is_empty());
assert!(!hints().is_empty());
}
#[test]
fn deserializes_partial_object() {
let h: InstallHints = serde_json::from_str(r#"{ "windows": "winget install x" }"#).unwrap();
assert_eq!(h.windows, "winget install x");
assert!(h.macos.is_empty() && h.linux.is_empty());
}
#[test]
fn serializes_without_empty_platforms() {
let json = serde_json::to_string(&hints()).unwrap();
assert!(!json.contains("linux"), "empty platforms omitted: {json}");
}
#[test]
fn current_matches_compile_target() {
let expected = if cfg!(target_os = "macos") {
Some(HostPlatform::MacOs)
} else if cfg!(target_os = "linux") {
Some(HostPlatform::Linux)
} else if cfg!(windows) {
Some(HostPlatform::Windows)
} else {
None
};
assert_eq!(HostPlatform::current(), expected);
}
}