use std::fmt;
use std::str::FromStr;
use indexmap::IndexSet;
use serde_with::{DeserializeFromStr, SerializeDisplay};
use crate::types::SortedSet;
use crate::Error;
use super::{parse, Stringable};
#[repr(C)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone)]
pub enum UseDepKind {
Enabled, Disabled, Equal, NotEqual, EnabledConditional, DisabledConditional, }
#[repr(C)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone)]
pub enum UseDepDefault {
Enabled, Disabled, }
#[derive(
DeserializeFromStr, SerializeDisplay, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone,
)]
pub struct UseDep {
pub(crate) flag: String,
pub(crate) kind: UseDepKind,
pub(crate) default: Option<UseDepDefault>,
}
impl fmt::Display for UseDep {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let default = match &self.default {
Some(UseDepDefault::Enabled) => "(+)",
Some(UseDepDefault::Disabled) => "(-)",
None => "",
};
let flag = self.flag();
match &self.kind {
UseDepKind::Enabled => write!(f, "{flag}{default}"),
UseDepKind::Disabled => write!(f, "-{flag}{default}"),
UseDepKind::Equal => write!(f, "{flag}{default}="),
UseDepKind::NotEqual => write!(f, "!{flag}{default}="),
UseDepKind::EnabledConditional => write!(f, "{flag}{default}?"),
UseDepKind::DisabledConditional => write!(f, "!{flag}{default}?"),
}
}
}
impl FromStr for UseDep {
type Err = Error;
fn from_str(s: &str) -> crate::Result<Self> {
Self::try_new(s)
}
}
impl FromStr for SortedSet<UseDep> {
type Err = Error;
fn from_str(s: &str) -> crate::Result<Self> {
s.split(',').map(UseDep::try_new).collect()
}
}
impl UseDep {
pub fn try_new(s: &str) -> crate::Result<Self> {
parse::use_dep(s)
}
pub fn kind(&self) -> &UseDepKind {
&self.kind
}
pub fn possible(&self) -> bool {
[UseDepKind::Enabled, UseDepKind::EnabledConditional, UseDepKind::Equal]
.iter()
.any(|x| x == &self.kind)
}
pub fn flag(&self) -> &str {
&self.flag
}
pub fn default(&self) -> Option<UseDepDefault> {
self.default
}
pub(crate) fn matches<S: Stringable>(&self, options: &IndexSet<S>) -> bool {
let flag = self.flag.as_str();
match &self.kind {
UseDepKind::EnabledConditional => options.contains(flag),
UseDepKind::DisabledConditional => !options.contains(flag),
_ => todo!(),
}
}
}