os2/
lib.rs

1#![doc = include_str!("../README.md")]
2
3mod linux;
4pub use linux::Linux as LinuxOs;
5
6use std::str::FromStr;
7use strum::{AsRefStr, Display, EnumIs};
8
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10#[cfg_attr(feature = "rune", derive(rune::Any))]
11#[derive(Debug, Hash, Eq, Clone, Copy, Default, Display, EnumIs, AsRefStr, PartialEq)]
12#[strum(serialize_all = "snake_case")]
13pub enum Os {
14    #[default]
15    #[strum(serialize = "unknown")]
16    Unknown,
17    #[strum(transparent)]
18    Linux(LinuxOs),
19    #[strum(serialize = "windows")]
20    Windows,
21    #[strum(serialize = "macos")]
22    MacOs,
23    #[strum(serialize = "unix")]
24    Unix,
25}
26
27impl Os {
28    pub fn linux() -> Self {
29        Os::Linux(LinuxOs::default())
30    }
31    /// Confirms if the current operating system is compatible with another.
32    /// # Examples
33    /// ```
34    /// use os2::Os;
35    /// let os = Os::Linux(os2::LinuxOs::Ubuntu);
36    /// assert!(os.compatible(&Os::Linux(os2::LinuxOs::Ubuntu)));
37    /// assert!(!os.compatible(&Os::Linux(os2::LinuxOs::Arch)));
38    /// assert!(os.compatible(&Os::Linux(os2::LinuxOs::Unknown)));
39    /// assert!(os.compatible(&Os::Unix));
40    /// ```
41    pub fn compatible(&self, other: &Os) -> bool {
42        match other {
43            Os::Unknown => true,
44            Os::Linux(LinuxOs::Unknown) => matches!(self, Os::Linux(_)),
45            Os::Linux(linux) => match self {
46                Os::Linux(other_linux) => linux == other_linux,
47                _ => false,
48            },
49            Os::Windows => self == &Os::Windows,
50            Os::MacOs => self == &Os::MacOs,
51            Os::Unix => matches!(self, Os::Linux(_) | Os::Unix | Os::MacOs),
52        }
53    }
54    /// Returns the next compatible operating system.
55    /// # Examples
56    /// ```
57    /// use os2::Os;
58    /// let os = Os::MacOs;
59    /// assert_eq!(os.next_compatible(), Some(Os::Unix));
60    /// let os = Os::Linux(os2::LinuxOs::Ubuntu);
61    /// assert_eq!(os.next_compatible(), Some(Os::Linux(os2::LinuxOs::Unknown)));
62    /// let os = Os::Unknown;
63    /// assert_eq!(os.next_compatible(), None);
64    /// ```
65    pub fn next_compatible(&self) -> Option<Os> {
66        match self {
67            Os::Unknown => None,
68            Os::Linux(linux) if linux.is_unknown() => Some(Os::Unix),
69            Os::Linux(_) => Some(Os::linux()),
70            Os::Windows => Some(Os::Unknown), //NOTE:Need to be confirmed
71            Os::MacOs => Some(Os::Unix),      //NOTE:Need to be confirmed
72            Os::Unix => Some(Os::Unknown),    //NOTE:Need to be confirmed
73        }
74    }
75}
76
77impl From<&str> for Os {
78    fn from(s: &str) -> Self {
79        if let Ok(os) = LinuxOs::from_str(s) {
80            Os::Linux(os)
81        } else {
82            match s {
83                "windows" => Os::Windows,
84                "macos" => Os::MacOs,
85                "unix" => Os::Unix,
86                _ => Os::Unknown,
87            }
88        }
89    }
90}
91
92impl From<&String> for Os {
93    fn from(s: &String) -> Self {
94        Os::from(s.as_str())
95    }
96}
97
98impl From<String> for Os {
99    fn from(s: String) -> Self {
100        Os::from(s.as_str())
101    }
102}
103/// Detect the current operating system.
104pub fn detect() -> Os {
105    if cfg!(target_os = "linux") {
106        Os::Linux(LinuxOs::detect())
107    } else if cfg!(target_os = "windows") {
108        Os::Windows
109    } else if cfg!(target_os = "macos") {
110        Os::MacOs
111    } else {
112        Os::Unknown
113    }
114}
115
116#[test]
117fn test_os_convert() {
118    assert_eq!(Os::Unknown.as_ref(), "unknown");
119    assert_eq!(Os::Linux(LinuxOs::Unknown).as_ref(), "linux");
120    assert_eq!(Os::from("linux"), Os::Linux(LinuxOs::Unknown));
121    assert_eq!(Os::from("manjaro"), Os::Linux(LinuxOs::Manjaro));
122    assert_eq!(Os::from("unknown"), Os::Unknown);
123}