use std::borrow::Cow;
use {
super::{
constraint::OptionConstraint, error::OptionError, scope::OptionScope, value::OptionValue,
},
crate::api::ModuleId,
};
#[derive(Debug, Clone)]
pub struct OptionSpec {
pub name: Cow<'static, str>,
pub short_form: Option<Cow<'static, str>>,
pub description: Cow<'static, str>,
pub default: OptionValue,
pub constraint: OptionConstraint,
pub scope: OptionScope,
pub owner: Option<ModuleId>,
}
impl OptionSpec {
#[must_use]
pub fn new(
name: impl Into<Cow<'static, str>>,
description: impl Into<Cow<'static, str>>,
default: OptionValue,
) -> Self {
Self {
name: name.into(),
description: description.into(),
default,
short_form: None,
constraint: OptionConstraint::none(),
scope: OptionScope::default(),
owner: None,
}
}
#[must_use]
pub fn with_short(mut self, short: impl Into<Cow<'static, str>>) -> Self {
self.short_form = Some(short.into());
self
}
#[must_use]
pub const fn with_constraint(mut self, constraint: OptionConstraint) -> Self {
self.constraint = constraint;
self
}
#[must_use]
pub const fn with_scope(mut self, scope: OptionScope) -> Self {
self.scope = scope;
self
}
#[must_use]
pub fn with_owner(mut self, owner: ModuleId) -> Self {
self.owner = Some(owner);
self
}
#[must_use]
pub const fn owner(&self) -> Option<&ModuleId> {
self.owner.as_ref()
}
#[must_use]
pub fn matches_name(&self, query: &str) -> bool {
self.name == query
|| self
.short_form
.as_ref()
.is_some_and(|s: &Cow<'static, str>| s.as_ref() == query)
}
pub fn validate(&self, value: &OptionValue) -> Result<(), OptionError> {
if !self.default.same_type(value) {
return Err(OptionError::TypeMismatch {
name: self.name.to_string(),
expected: self.default.type_name(),
got: value.type_name(),
});
}
self.constraint
.validate(value)
.map_err(|e| OptionError::ValidationFailed {
name: self.name.to_string(),
reason: e.to_string(),
})
}
}