use std::collections::btree_set::IntoIter;
use std::collections::VecDeque;
use std::fmt::Display;
use std::{
collections::{BTreeSet, HashMap, HashSet},
hash::Hash,
};
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum ConfigType {
Bool,
Tristate,
String,
Int,
Hex,
}
impl Display for ConfigType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ConfigType::Bool => f.write_str("bool"),
ConfigType::Tristate => f.write_str("tristate"),
ConfigType::String => f.write_str("string"),
ConfigType::Int => f.write_str("int"),
ConfigType::Hex => f.write_str("hex"),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub enum Expr {
Sym(String), Eq(BTreeSet<Expr>),
Ne(BTreeSet<Expr>),
Lt(BTreeSet<Expr>),
Gt(BTreeSet<Expr>),
Lte(BTreeSet<Expr>),
Gte(BTreeSet<Expr>),
And(BTreeSet<Expr>),
Or(BTreeSet<Expr>),
Sub(Box<Expr>),
Not(Box<Expr>),
}
impl Expr {
pub fn is_sym(&self) -> bool {
match self {
Self::Sym(_) => true,
_ => false,
}
}
pub fn is_not(&self) -> bool {
match self {
Self::Not(_) => true,
_ => false,
}
}
pub fn is_sub(&self) -> bool {
match self {
Self::Sub(_) => true,
_ => false,
}
}
pub fn is_comparison(&self) -> bool {
match self {
Self::Eq(_)
| Self::Ne(_)
| Self::Lt(_)
| Self::Gt(_)
| Self::Lte(_)
| Self::Gte(_)
| Self::And(_)
| Self::Or(_) => true,
_ => false,
}
}
pub fn contains(&self, expr: &Expr) -> bool {
match self {
Self::Sym(_) => false,
Self::Sub(b) | Self::Not(b) => b.contains(expr),
Self::Eq(s)
| Self::Ne(s)
| Self::Lt(s)
| Self::Gt(s)
| Self::Lte(s)
| Self::Gte(s)
| Self::And(s)
| Self::Or(s) => s.contains(expr),
}
}
pub fn is_eq(&self) -> bool {
match self {
Self::Eq(_) => true,
_ => false,
}
}
pub fn is_ne(&self) -> bool {
match self {
Self::Ne(_) => true,
_ => false,
}
}
pub fn is_lt(&self) -> bool {
match self {
Self::Lt(_) => true,
_ => false,
}
}
pub fn is_gt(&self) -> bool {
match self {
Self::Gt(_) => true,
_ => false,
}
}
pub fn is_gte(&self) -> bool {
match self {
Self::Gte(_) => true,
_ => false,
}
}
pub fn is_lte(&self) -> bool {
match self {
Self::Lte(_) => true,
_ => false,
}
}
pub fn is_and(&self) -> bool {
match self {
Self::And(_) => true,
_ => false,
}
}
pub fn is_or(&self) -> bool {
match self {
Self::Or(_) => true,
_ => false,
}
}
pub fn get_sym(&self) -> Option<String> {
match self {
Self::Sym(s) => Some(s.to_string()),
_ => None,
}
}
pub fn get_not_expr(&self) -> Option<Expr> {
match self {
Self::Not(e) => Some(e.as_ref().clone()),
_ => None,
}
}
pub fn get_sub_expr(&self) -> Option<Expr> {
match self {
Self::Sub(e) => Some(e.as_ref().clone()),
_ => None,
}
}
pub fn len(&self) -> usize {
match self {
Self::Eq(s)
| Self::Ne(s)
| Self::Lt(s)
| Self::Gt(s)
| Self::Lte(s)
| Self::Gte(s)
| Self::And(s)
| Self::Or(s) => s.len(),
_ => 1,
}
}
}
impl IntoIterator for Expr {
type Item = Expr;
type IntoIter = IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
match self {
Self::Eq(s)
| Self::Ne(s)
| Self::Lt(s)
| Self::Gt(s)
| Self::Lte(s)
| Self::Gte(s)
| Self::And(s)
| Self::Or(s) => s.into_iter(),
Self::Sym(s) => {
let mut set = BTreeSet::new();
set.insert(Expr::Sym(s.to_string()));
set.into_iter()
}
Self::Sub(s) | Self::Not(s) => {
let mut set = BTreeSet::new();
set.insert(*s.clone());
set.into_iter()
}
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Dependency {
expr: Expr,
}
impl Dependency {
pub fn expr(&self) -> Expr {
self.expr.clone()
}
pub fn new(expr: &Expr) -> Self {
Dependency { expr: expr.clone() }
}
pub fn len(&self) -> usize {
return self.expr.len();
}
pub fn contains(&self, expr: &Expr) -> bool {
self.expr.contains(expr)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ConfigTypeInstance {
config_type: ConfigType,
dependency: Dependency,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Range {
pub(super) lhs: i64,
pub(super) rhs: i64,
pub(super) dependency: Option<Dependency>,
}
impl Range {
pub fn lhs(&self) -> i64 {
self.lhs
}
pub fn rhs(&self) -> i64 {
self.rhs
}
pub fn dependency(&self) -> &Option<Dependency> {
&self.dependency
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Config {
pub(super) name: String,
pub(super) prompt: Option<String>,
pub(super) types: HashMap<ConfigType, Option<Dependency>>,
pub(super) defaults: HashMap<Expr, Option<Dependency>>,
pub(super) dependencies: HashSet<Dependency>,
pub(super) reverse_dependencies: HashMap<String, Option<Dependency>>,
pub(super) weak_dependencies: HashMap<String, Option<Dependency>>,
pub(super) menu_dependencies: HashSet<Dependency>,
pub(super) range: Option<Range>,
pub(super) help: VecDeque<String>,
}
impl Config {
pub fn create(name: &str) -> Self {
Self {
name: name.to_string(),
prompt: None,
types: HashMap::new(),
defaults: HashMap::new(),
dependencies: HashSet::new(),
reverse_dependencies: HashMap::new(),
weak_dependencies: HashMap::new(),
menu_dependencies: HashSet::new(),
range: None,
help: VecDeque::new(),
}
}
}