use core::fmt;
use core::str::FromStr;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "arbitrary")]
use arbitrary::Arbitrary;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[non_exhaustive]
pub enum OsTypeError {
UnknownOperatingSystem,
}
impl fmt::Display for OsTypeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::UnknownOperatingSystem => write!(f, "unknown operating system"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for OsTypeError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[non_exhaustive]
pub enum OsType {
LINUX,
MACOS,
WINDOWS,
FREEBSD,
OPENBSD,
NETBSD,
DRAGONFLY,
SOLARIS,
ILLUMOS,
ANDROID,
IOS,
REDOX,
FUCHSIA,
HERMIT,
VXWORKS,
AIX,
HAIKU,
}
impl OsType {
#[must_use]
pub const fn current() -> Self {
#[cfg(target_os = "linux")]
return Self::LINUX;
#[cfg(target_os = "macos")]
return Self::MACOS;
#[cfg(target_os = "windows")]
return Self::WINDOWS;
#[cfg(target_os = "freebsd")]
return Self::FREEBSD;
#[cfg(target_os = "openbsd")]
return Self::OPENBSD;
#[cfg(target_os = "netbsd")]
return Self::NETBSD;
#[cfg(target_os = "dragonfly")]
return Self::DRAGONFLY;
#[cfg(target_os = "solaris")]
return Self::SOLARIS;
#[cfg(target_os = "illumos")]
return Self::ILLUMOS;
#[cfg(target_os = "android")]
return Self::ANDROID;
#[cfg(target_os = "ios")]
return Self::IOS;
#[cfg(target_os = "redox")]
return Self::REDOX;
#[cfg(target_os = "fuchsia")]
return Self::FUCHSIA;
#[cfg(target_os = "hermit")]
return Self::HERMIT;
#[cfg(target_os = "vxworks")]
return Self::VXWORKS;
#[cfg(target_os = "aix")]
return Self::AIX;
#[cfg(target_os = "haiku")]
return Self::HAIKU;
#[cfg(not(any(
target_os = "linux",
target_os = "macos",
target_os = "windows",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly",
target_os = "solaris",
target_os = "illumos",
target_os = "android",
target_os = "ios",
target_os = "redox",
target_os = "fuchsia",
target_os = "hermit",
target_os = "vxworks",
target_os = "aix",
target_os = "haiku",
)))]
{
panic!("unsupported target operating system")
}
}
#[must_use]
pub const fn as_str(&self) -> &'static str {
match self {
Self::LINUX => "linux",
Self::MACOS => "macos",
Self::WINDOWS => "windows",
Self::FREEBSD => "freebsd",
Self::OPENBSD => "openbsd",
Self::NETBSD => "netbsd",
Self::DRAGONFLY => "dragonfly",
Self::SOLARIS => "solaris",
Self::ILLUMOS => "illumos",
Self::ANDROID => "android",
Self::IOS => "ios",
Self::REDOX => "redox",
Self::FUCHSIA => "fuchsia",
Self::HERMIT => "hermit",
Self::VXWORKS => "vxworks",
Self::AIX => "aix",
Self::HAIKU => "haiku",
}
}
#[must_use]
pub const fn is_unix(&self) -> bool {
matches!(
self,
Self::LINUX
| Self::MACOS
| Self::FREEBSD
| Self::OPENBSD
| Self::NETBSD
| Self::DRAGONFLY
| Self::SOLARIS
| Self::ILLUMOS
| Self::ANDROID
| Self::IOS
| Self::AIX
| Self::HAIKU
)
}
#[must_use]
pub const fn is_bsd(&self) -> bool {
matches!(
self,
Self::FREEBSD | Self::OPENBSD | Self::NETBSD | Self::DRAGONFLY | Self::MACOS
)
}
#[must_use]
pub const fn is_windows(&self) -> bool {
matches!(self, Self::WINDOWS)
}
#[must_use]
pub const fn is_mobile(&self) -> bool {
matches!(self, Self::ANDROID | Self::IOS)
}
#[must_use]
pub const fn is_desktop(&self) -> bool {
matches!(
self,
Self::LINUX | Self::MACOS | Self::WINDOWS | Self::FREEBSD | Self::HAIKU
)
}
#[must_use]
pub const fn is_embedded(&self) -> bool {
matches!(self, Self::VXWORKS)
}
#[must_use]
pub const fn is_microkernel(&self) -> bool {
matches!(self, Self::REDOX | Self::FUCHSIA)
}
#[must_use]
pub const fn is_posix(&self) -> bool {
self.is_unix()
}
#[must_use]
pub const fn is_tier1(&self) -> bool {
matches!(self, Self::LINUX | Self::MACOS | Self::WINDOWS)
}
#[must_use]
pub const fn family(&self) -> &'static str {
if self.is_unix() {
"unix"
} else if self.is_windows() {
"windows"
} else {
"unknown"
}
}
}
impl TryFrom<&str> for OsType {
type Error = OsTypeError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
s.parse()
}
}
impl FromStr for OsType {
type Err = OsTypeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"linux" => Ok(Self::LINUX),
"macos" | "mac" | "osx" | "darwin" | "os x" => Ok(Self::MACOS),
"windows" | "win" => Ok(Self::WINDOWS),
"freebsd" => Ok(Self::FREEBSD),
"openbsd" => Ok(Self::OPENBSD),
"netbsd" => Ok(Self::NETBSD),
"dragonfly" | "dragonfly bsd" => Ok(Self::DRAGONFLY),
"solaris" => Ok(Self::SOLARIS),
"illumos" => Ok(Self::ILLUMOS),
"android" => Ok(Self::ANDROID),
"ios" | "iphone" => Ok(Self::IOS),
"redox" => Ok(Self::REDOX),
"fuchsia" => Ok(Self::FUCHSIA),
"hermit" => Ok(Self::HERMIT),
"vxworks" => Ok(Self::VXWORKS),
"aix" => Ok(Self::AIX),
"haiku" => Ok(Self::HAIKU),
_ => Err(OsTypeError::UnknownOperatingSystem),
}
}
}
impl fmt::Display for OsType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_as_str() {
assert_eq!(OsType::LINUX.as_str(), "linux");
assert_eq!(OsType::MACOS.as_str(), "macos");
assert_eq!(OsType::WINDOWS.as_str(), "windows");
assert_eq!(OsType::FREEBSD.as_str(), "freebsd");
assert_eq!(OsType::OPENBSD.as_str(), "openbsd");
assert_eq!(OsType::NETBSD.as_str(), "netbsd");
assert_eq!(OsType::DRAGONFLY.as_str(), "dragonfly");
assert_eq!(OsType::SOLARIS.as_str(), "solaris");
assert_eq!(OsType::ILLUMOS.as_str(), "illumos");
assert_eq!(OsType::ANDROID.as_str(), "android");
assert_eq!(OsType::IOS.as_str(), "ios");
assert_eq!(OsType::REDOX.as_str(), "redox");
assert_eq!(OsType::FUCHSIA.as_str(), "fuchsia");
assert_eq!(OsType::HERMIT.as_str(), "hermit");
assert_eq!(OsType::VXWORKS.as_str(), "vxworks");
assert_eq!(OsType::AIX.as_str(), "aix");
assert_eq!(OsType::HAIKU.as_str(), "haiku");
}
#[test]
fn test_is_unix() {
assert!(OsType::LINUX.is_unix());
assert!(OsType::MACOS.is_unix());
assert!(OsType::FREEBSD.is_unix());
assert!(OsType::OPENBSD.is_unix());
assert!(OsType::NETBSD.is_unix());
assert!(OsType::DRAGONFLY.is_unix());
assert!(OsType::SOLARIS.is_unix());
assert!(OsType::ILLUMOS.is_unix());
assert!(OsType::ANDROID.is_unix());
assert!(OsType::IOS.is_unix());
assert!(OsType::AIX.is_unix());
assert!(OsType::HAIKU.is_unix());
assert!(!OsType::WINDOWS.is_unix());
assert!(!OsType::REDOX.is_unix());
assert!(!OsType::FUCHSIA.is_unix());
}
#[test]
fn test_is_bsd() {
assert!(OsType::FREEBSD.is_bsd());
assert!(OsType::OPENBSD.is_bsd());
assert!(OsType::NETBSD.is_bsd());
assert!(OsType::DRAGONFLY.is_bsd());
assert!(OsType::MACOS.is_bsd());
assert!(!OsType::LINUX.is_bsd());
assert!(!OsType::WINDOWS.is_bsd());
}
#[test]
fn test_is_windows() {
assert!(OsType::WINDOWS.is_windows());
assert!(!OsType::LINUX.is_windows());
assert!(!OsType::MACOS.is_windows());
}
#[test]
fn test_is_mobile() {
assert!(OsType::ANDROID.is_mobile());
assert!(OsType::IOS.is_mobile());
assert!(!OsType::LINUX.is_mobile());
assert!(!OsType::WINDOWS.is_mobile());
}
#[test]
fn test_is_desktop() {
assert!(OsType::LINUX.is_desktop());
assert!(OsType::MACOS.is_desktop());
assert!(OsType::WINDOWS.is_desktop());
assert!(OsType::FREEBSD.is_desktop());
assert!(OsType::HAIKU.is_desktop());
assert!(!OsType::ANDROID.is_desktop());
assert!(!OsType::IOS.is_desktop());
}
#[test]
fn test_is_embedded() {
assert!(OsType::VXWORKS.is_embedded());
assert!(!OsType::LINUX.is_embedded());
}
#[test]
fn test_is_microkernel() {
assert!(OsType::REDOX.is_microkernel());
assert!(OsType::FUCHSIA.is_microkernel());
assert!(!OsType::LINUX.is_microkernel());
}
#[test]
fn test_is_posix() {
assert!(OsType::LINUX.is_posix());
assert!(OsType::MACOS.is_posix());
assert!(!OsType::WINDOWS.is_posix());
}
#[test]
fn test_is_tier1() {
assert!(OsType::LINUX.is_tier1());
assert!(OsType::MACOS.is_tier1());
assert!(OsType::WINDOWS.is_tier1());
assert!(!OsType::FREEBSD.is_tier1());
}
#[test]
fn test_family() {
assert_eq!(OsType::LINUX.family(), "unix");
assert_eq!(OsType::MACOS.family(), "unix");
assert_eq!(OsType::WINDOWS.family(), "windows");
}
#[test]
fn test_from_str() {
assert_eq!("linux".parse::<OsType>().unwrap(), OsType::LINUX);
assert_eq!("macos".parse::<OsType>().unwrap(), OsType::MACOS);
assert_eq!("mac".parse::<OsType>().unwrap(), OsType::MACOS);
assert_eq!("darwin".parse::<OsType>().unwrap(), OsType::MACOS);
assert_eq!("windows".parse::<OsType>().unwrap(), OsType::WINDOWS);
assert_eq!("freebsd".parse::<OsType>().unwrap(), OsType::FREEBSD);
assert_eq!("openbsd".parse::<OsType>().unwrap(), OsType::OPENBSD);
assert_eq!("netbsd".parse::<OsType>().unwrap(), OsType::NETBSD);
assert_eq!("dragonfly".parse::<OsType>().unwrap(), OsType::DRAGONFLY);
assert_eq!("solaris".parse::<OsType>().unwrap(), OsType::SOLARIS);
assert_eq!("illumos".parse::<OsType>().unwrap(), OsType::ILLUMOS);
assert_eq!("android".parse::<OsType>().unwrap(), OsType::ANDROID);
assert_eq!("ios".parse::<OsType>().unwrap(), OsType::IOS);
assert_eq!("redox".parse::<OsType>().unwrap(), OsType::REDOX);
assert_eq!("fuchsia".parse::<OsType>().unwrap(), OsType::FUCHSIA);
assert_eq!("hermit".parse::<OsType>().unwrap(), OsType::HERMIT);
assert_eq!("vxworks".parse::<OsType>().unwrap(), OsType::VXWORKS);
assert_eq!("aix".parse::<OsType>().unwrap(), OsType::AIX);
assert_eq!("haiku".parse::<OsType>().unwrap(), OsType::HAIKU);
assert_eq!("LINUX".parse::<OsType>().unwrap(), OsType::LINUX);
assert_eq!("Windows".parse::<OsType>().unwrap(), OsType::WINDOWS);
}
#[test]
fn test_from_str_error() {
assert!("unknown".parse::<OsType>().is_err());
assert!("".parse::<OsType>().is_err());
}
#[test]
fn test_display() {
assert_eq!(format!("{}", OsType::LINUX), "linux");
assert_eq!(format!("{}", OsType::MACOS), "macos");
assert_eq!(format!("{}", OsType::WINDOWS), "windows");
}
#[test]
fn test_current() {
let _os = OsType::current();
}
#[test]
fn test_copy() {
let os = OsType::LINUX;
let os2 = os;
assert_eq!(os, os2);
}
#[test]
fn test_clone() {
let os = OsType::LINUX;
let os2 = os.clone();
assert_eq!(os, os2);
}
#[test]
fn test_equality() {
assert_eq!(OsType::LINUX, OsType::LINUX);
assert_ne!(OsType::LINUX, OsType::WINDOWS);
}
#[test]
fn test_ordering() {
assert!(OsType::LINUX < OsType::ANDROID); assert!(OsType::LINUX < OsType::FREEBSD); }
}