use std::fmt;
use std::str::FromStr;
use indexmap::IndexSet;
use serde_with::{DeserializeFromStr, SerializeDisplay};
use crate::Error;
use crate::types::SortedSet;
use super::{Stringable, parse};
#[repr(C)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone)]
pub enum UseDepKind {
Enabled, Equal, Conditional, }
#[derive(
DeserializeFromStr, SerializeDisplay, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone,
)]
pub struct UseDep {
pub(crate) flag: String,
pub(crate) kind: UseDepKind,
pub(crate) enabled: bool,
pub(crate) default: Option<bool>,
}
impl fmt::Display for UseDep {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let default = match &self.default {
Some(true) => "(+)",
Some(false) => "(-)",
None => "",
};
let flag = &self.flag;
match (&self.kind, &self.enabled) {
(UseDepKind::Enabled, true) => write!(f, "{flag}{default}"),
(UseDepKind::Enabled, false) => write!(f, "-{flag}{default}"),
(UseDepKind::Equal, true) => write!(f, "{flag}{default}="),
(UseDepKind::Equal, false) => write!(f, "!{flag}{default}="),
(UseDepKind::Conditional, true) => write!(f, "{flag}{default}?"),
(UseDepKind::Conditional, false) => 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 flag(&self) -> &str {
&self.flag
}
pub fn enabled(&self) -> bool {
self.enabled
}
pub fn default(&self) -> Option<bool> {
self.default
}
pub(crate) fn matches<S: Stringable>(&self, options: &IndexSet<S>) -> bool {
if self.kind == UseDepKind::Conditional {
!(self.enabled ^ options.contains(self.flag()))
} else {
todo!()
}
}
}