use std::str::FromStr;
use serde::{Serialize, Deserialize};
use thiserror::Error;
use crate::types::*;
use crate::util::*;
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Suitability)]
#[serde(deny_unknown_fields)]
pub enum FlagType {
#[default]
Params,
Scratchpad,
CommonArg
}
#[derive(Debug, Error)]
pub enum GetFlagError {
#[error(transparent)]
StringSourceError(#[from] Box<StringSourceError>),
#[error("The specified StringSource returned None where it had to be Some.")]
StringSourceIsNone,
#[error("Tried to use FlagType::CommonArg outside of a common context.")]
NotInCommonContext
}
impl From<StringSourceError> for GetFlagError {
fn from(value: StringSourceError) -> Self {
Self::StringSourceError(Box::new(value))
}
}
impl FlagType {
pub fn get(&self, name: &str, task_state: &TaskStateView) -> Result<bool, GetFlagError> {
Ok(match self {
Self::Params => task_state.params .flags.contains(name),
Self::Scratchpad => task_state.scratchpad.flags.contains(name),
Self::CommonArg => task_state.common_args.ok_or(GetFlagError::NotInCommonContext)?.flags.contains(name)
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(remote = "Self")]
pub struct FlagRef {
#[serde(default, skip_serializing_if = "is_default")]
pub r#type: FlagType,
pub name: StringSource
}
impl Suitability for FlagRef {
fn assert_suitability(&self, config: &Cleaner) {
match (&self.r#type, &self.name) {
(FlagType::Params, StringSource::String(name)) => assert!(config.docs.flags.contains_key(name), "Undocumented Flag: {name}"),
(FlagType::CommonArg | FlagType::Scratchpad, StringSource::String(_)) => {},
_ => panic!("Unsuitable FlagRef: {self:?}")
}
}
}
impl FlagRef {
pub fn get(&self, task_state: &TaskStateView) -> Result<bool, GetFlagError> {
debug!(FlagRef::get, self);
self.r#type.get(get_str!(self.name, task_state, GetFlagError), task_state)
}
}
impl FromStr for FlagRef {
type Err = std::convert::Infallible;
fn from_str(name: &str) -> Result<FlagRef, Self::Err> {
Ok(name.into())
}
}
impl From<StringSource> for FlagRef {
fn from(name: StringSource) -> Self {
Self {
r#type: Default::default(),
name
}
}
}
impl From<String> for FlagRef {
fn from(name: String) -> Self {
StringSource::String(name).into()
}
}
impl From<&str> for FlagRef {
fn from(name: &str) -> Self {
name.to_string().into()
}
}
string_or_struct_magic!(FlagRef);