use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OptionValue {
Bool(bool),
Integer(i64),
String(String),
Choice {
value: String,
choices: Vec<String>,
},
}
impl OptionValue {
#[must_use]
pub const fn bool(value: bool) -> Self {
Self::Bool(value)
}
#[must_use]
pub const fn int(value: i64) -> Self {
Self::Integer(value)
}
#[must_use]
pub fn string(value: impl Into<String>) -> Self {
Self::String(value.into())
}
#[must_use]
pub fn choice(value: impl Into<String>, choices: Vec<String>) -> Self {
let value = value.into();
debug_assert!(!choices.is_empty(), "choices must not be empty");
debug_assert!(choices.contains(&value), "value must be in choices");
Self::Choice { value, choices }
}
#[must_use]
pub const fn as_bool(&self) -> Option<bool> {
match self {
Self::Bool(b) => Some(*b),
_ => None,
}
}
#[must_use]
pub const fn as_int(&self) -> Option<i64> {
match self {
Self::Integer(i) => Some(*i),
_ => None,
}
}
#[must_use]
pub fn as_str(&self) -> Option<&str> {
match self {
Self::String(s) => Some(s),
Self::Choice { value, .. } => Some(value),
_ => None,
}
}
#[must_use]
pub const fn type_name(&self) -> &'static str {
match self {
Self::Bool(_) => "bool",
Self::Integer(_) => "integer",
Self::String(_) => "string",
Self::Choice { .. } => "choice",
}
}
#[must_use]
pub const fn same_type(&self, other: &Self) -> bool {
matches!(
(self, other),
(Self::Bool(_), Self::Bool(_))
| (Self::Integer(_), Self::Integer(_))
| (Self::String(_), Self::String(_))
| (Self::Choice { .. }, Self::Choice { .. })
)
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl fmt::Display for OptionValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Bool(b) => write!(f, "{b}"),
Self::Integer(i) => write!(f, "{i}"),
Self::String(s) => write!(f, "{s}"),
Self::Choice { value, .. } => write!(f, "{value}"),
}
}
}