1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
// OS.rs
// by Lut99
//
// Created:
// 01 May 2024, 10:10:50
// Last edited:
// 01 May 2024, 10:27:41
// Auto updated?
// Yes
//
// Description:
//! Implements a OS-string enum that allows us to communicate operating
//! system (types) to/from users.
//
use std::error::Error;
use std::fmt::{Display, Formatter, Result as FResult};
use std::hash::Hash;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
/***** ERRORS *****/
/// Defines the error that may occur when parsing operating systems
#[derive(Debug)]
pub enum ParseError {
/// Running on an OS we do not known.
#[cfg(not(any(windows, target_os = "macos", target_os = "linux")))]
UnknownLocalOs,
/// Could not deserialize the given string
UnknownOs { raw: String },
}
impl Display for ParseError {
fn fmt(&self, f: &mut Formatter<'_>) -> FResult {
use ParseError::*;
match self {
#[cfg(not(any(windows, target_os = "macos", target_os = "linux")))]
UnknownLocalOs => write!(f, "Running on an unknown OS, cannot automatically resolve '$LOCAL' OS string"),
UnknownOs { raw } => write!(f, "Unknown operating system '{raw}'"),
}
}
}
impl Error for ParseError {}
/***** AUXILLARY *****/
/// A formatter for operating systems that writes it in a way that is used to download cfssl binaries.
#[derive(Debug)]
pub struct OsCfsslFormatter<'o> {
/// The operating system to format.
os: &'o Os,
}
impl<'o> Display for OsCfsslFormatter<'o> {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> FResult {
match self.os {
Os::Windows => write!(f, "windows"),
Os::MacOS => write!(f, "darwin"),
Os::Linux => write!(f, "linux"),
}
}
}
/***** LIBRARY *****/
/// The Os enum defines possible operating systems that we know of and love
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum Os {
/// Windows 95/98/2000/XP/Vista/7/8/10/11/w/e
#[serde(alias = "win")]
Windows,
/// Apple's operating system
#[serde(alias = "darwin")]
MacOS,
/// Linux of any shape.
Linux,
}
impl Os {
/// Constant referring to the compiled (=host) operating system
#[cfg(windows)]
pub const HOST: Self = Self::Windows;
#[cfg(target_os = "macos")]
pub const HOST: Self = Self::MacOS;
#[cfg(target_os = "linux")]
pub const HOST: Self = Self::Linux;
/// Returns if this operating system points to Windows.
///
/// # Returns
/// True if we're [`Os::Windows`], or false otherwise.
#[inline]
pub fn is_windows(&self) -> bool { matches!(self, Self::Windows) }
/// Returns if this operating system is Unix-compatible.
///
/// # Returns
/// True if we're [`Os::MacOS`] or [`Os::Linux`], false if we're [`Os::Windows`].
#[inline]
pub fn is_unix(&self) -> bool { matches!(self, Self::MacOS) || matches!(self, Self::Linux) }
/// Returns if this operating system points to macOS.
///
/// # Returns
/// True if we're [`Os::MacOS`], or false otherwise.
#[inline]
pub fn is_macos(&self) -> bool { matches!(self, Self::MacOS) }
/// Returns if this operating system points to Linux.
///
/// # Returns
/// True if we're [`Os::Linux`], or false otherwise.
#[inline]
pub fn is_linux(&self) -> bool { matches!(self, Self::Linux) }
/// Allows one to serialize the operating system for use to download cfssl binaries.
///
/// # Returns
/// An `OsCfsslFormatter` that implements [`Display`]` in a cfssl-compatible way.
#[inline]
pub fn cfssl(&self) -> OsCfsslFormatter { OsCfsslFormatter { os: self } }
}
impl Display for Os {
fn fmt(&self, f: &mut Formatter<'_>) -> FResult {
match self {
Self::Windows => write!(f, "Windows"),
Self::MacOS => write!(f, "macOS"),
Self::Linux => write!(f, "Linux"),
}
}
}
impl FromStr for Os {
type Err = ParseError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"win" | "windows" => Ok(Self::Windows),
"darwin" | "macos" => Ok(Self::MacOS),
"linux" => Ok(Self::Linux),
// Meta-argument for resolving the local architecture
#[cfg(windows)]
"$LOCAL" => Ok(Self::Windows),
#[cfg(target_os = "macos")]
"$LOCAL" => Ok(Self::MacOS),
#[cfg(target_os = "linux")]
"$LOCAL" => Ok(Self::Linux),
#[cfg(not(any(windows, target_os = "macos", target_os = "linux")))]
"$LOCAL" => Err(ParseError::UnknownLocalOs),
raw => Err(ParseError::UnknownOs { raw: raw.to_string() }),
}
}
}