1use std::collections::btree_set::IntoIter;
63use std::collections::VecDeque;
64use std::fmt::Display;
65use std::{
66    collections::{BTreeSet, HashMap, HashSet},
67    hash::Hash,
68};
69
70#[derive(Clone, Debug, Eq, PartialEq, Hash)]
73pub enum ConfigType {
74    Bool,
75    Tristate,
76    String,
77    Int,
78    Hex,
79}
80
81impl Display for ConfigType {
83    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84        match self {
85            ConfigType::Bool => f.write_str("bool"),
86            ConfigType::Tristate => f.write_str("tristate"),
87            ConfigType::String => f.write_str("string"),
88            ConfigType::Int => f.write_str("int"),
89            ConfigType::Hex => f.write_str("hex"),
90        }
91    }
92}
93
94#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
99pub enum Expr {
100    Sym(String), Eq(BTreeSet<Expr>),
103    Ne(BTreeSet<Expr>),
104    Lt(BTreeSet<Expr>),
105    Gt(BTreeSet<Expr>),
106    Lte(BTreeSet<Expr>),
107    Gte(BTreeSet<Expr>),
108    And(BTreeSet<Expr>),
109    Or(BTreeSet<Expr>),
110    Sub(Box<Expr>),
111    Not(Box<Expr>),
112}
113
114impl Expr {
115    pub fn is_sym(&self) -> bool {
116        match self {
117            Self::Sym(_) => true,
118            _ => false,
119        }
120    }
121
122    pub fn is_not(&self) -> bool {
123        match self {
124            Self::Not(_) => true,
125            _ => false,
126        }
127    }
128
129    pub fn is_sub(&self) -> bool {
130        match self {
131            Self::Sub(_) => true,
132            _ => false,
133        }
134    }
135
136    pub fn is_comparison(&self) -> bool {
137        match self {
138            Self::Eq(_)
139            | Self::Ne(_)
140            | Self::Lt(_)
141            | Self::Gt(_)
142            | Self::Lte(_)
143            | Self::Gte(_)
144            | Self::And(_)
145            | Self::Or(_) => true,
146            _ => false,
147        }
148    }
149
150    pub fn contains(&self, expr: &Expr) -> bool {
151        match self {
152            Self::Sym(_) => false,
153            Self::Sub(b) | Self::Not(b) => b.contains(expr),
154            Self::Eq(s)
155            | Self::Ne(s)
156            | Self::Lt(s)
157            | Self::Gt(s)
158            | Self::Lte(s)
159            | Self::Gte(s)
160            | Self::And(s)
161            | Self::Or(s) => s.contains(expr),
162        }
163    }
164
165    pub fn is_eq(&self) -> bool {
166        match self {
167            Self::Eq(_) => true,
168            _ => false,
169        }
170    }
171    pub fn is_ne(&self) -> bool {
172        match self {
173            Self::Ne(_) => true,
174            _ => false,
175        }
176    }
177    pub fn is_lt(&self) -> bool {
178        match self {
179            Self::Lt(_) => true,
180            _ => false,
181        }
182    }
183    pub fn is_gt(&self) -> bool {
184        match self {
185            Self::Gt(_) => true,
186            _ => false,
187        }
188    }
189    pub fn is_gte(&self) -> bool {
190        match self {
191            Self::Gte(_) => true,
192            _ => false,
193        }
194    }
195    pub fn is_lte(&self) -> bool {
196        match self {
197            Self::Lte(_) => true,
198            _ => false,
199        }
200    }
201    pub fn is_and(&self) -> bool {
202        match self {
203            Self::And(_) => true,
204            _ => false,
205        }
206    }
207    pub fn is_or(&self) -> bool {
208        match self {
209            Self::Or(_) => true,
210            _ => false,
211        }
212    }
213
214    pub fn get_sym(&self) -> Option<String> {
215        match self {
216            Self::Sym(s) => Some(s.to_string()),
217            _ => None,
218        }
219    }
220
221    pub fn get_not_expr(&self) -> Option<Expr> {
222        match self {
223            Self::Not(e) => Some(e.as_ref().clone()),
224            _ => None,
225        }
226    }
227
228    pub fn get_sub_expr(&self) -> Option<Expr> {
229        match self {
230            Self::Sub(e) => Some(e.as_ref().clone()),
231            _ => None,
232        }
233    }
234
235    pub fn len(&self) -> usize {
236        match self {
237            Self::Eq(s)
238            | Self::Ne(s)
239            | Self::Lt(s)
240            | Self::Gt(s)
241            | Self::Lte(s)
242            | Self::Gte(s)
243            | Self::And(s)
244            | Self::Or(s) => s.len(),
245            _ => 1,
246        }
247    }
248}
249
250impl IntoIterator for Expr {
251    type Item = Expr;
252    type IntoIter = IntoIter<Self::Item>;
253    fn into_iter(self) -> Self::IntoIter {
254        match self {
255            Self::Eq(s)
256            | Self::Ne(s)
257            | Self::Lt(s)
258            | Self::Gt(s)
259            | Self::Lte(s)
260            | Self::Gte(s)
261            | Self::And(s)
262            | Self::Or(s) => s.into_iter(),
263            Self::Sym(s) => {
264                let mut set = BTreeSet::new();
265                set.insert(Expr::Sym(s.to_string()));
266                set.into_iter()
267            }
268            Self::Sub(s) | Self::Not(s) => {
269                let mut set = BTreeSet::new();
270                set.insert(*s.clone());
271                set.into_iter()
272            }
273        }
274    }
275}
276
277#[derive(Clone, Debug, Eq, PartialEq, Hash)]
280pub struct Dependency {
281    expr: Expr,
282}
283
284impl Dependency {
285    pub fn expr(&self) -> Expr {
286        self.expr.clone()
287    }
288
289    pub fn new(expr: &Expr) -> Self {
290        Dependency { expr: expr.clone() }
291    }
292
293    pub fn len(&self) -> usize {
294        return self.expr.len();
295    }
296
297    pub fn contains(&self, expr: &Expr) -> bool {
298        self.expr.contains(expr)
299    }
300}
301
302#[derive(Clone, Debug, Eq, PartialEq)]
304pub struct ConfigTypeInstance {
305    config_type: ConfigType,
306    dependency: Dependency,
307}
308
309#[derive(Clone, Debug, Eq, PartialEq)]
312pub struct Range {
313    pub(super) lhs: i64,
314    pub(super) rhs: i64,
315    pub(super) dependency: Option<Dependency>,
316}
317
318impl Range {
319    pub fn lhs(&self) -> i64 {
320        self.lhs
321    }
322    pub fn rhs(&self) -> i64 {
323        self.rhs
324    }
325    pub fn dependency(&self) -> &Option<Dependency> {
326        &self.dependency
327    }
328}
329
330#[derive(Clone, Debug, Eq, PartialEq)]
333pub struct Config {
334    pub(super) name: String,
335    pub(super) prompt: Option<String>,
336    pub(super) types: HashMap<ConfigType, Option<Dependency>>,
337    pub(super) defaults: HashMap<Expr, Option<Dependency>>,
338    pub(super) dependencies: HashSet<Dependency>,
339    pub(super) reverse_dependencies: HashMap<String, Option<Dependency>>,
340    pub(super) weak_dependencies: HashMap<String, Option<Dependency>>,
341    pub(super) menu_dependencies: HashSet<Dependency>,
342    pub(super) range: Option<Range>,
343    pub(super) help: VecDeque<String>,
344}
345
346impl Config {
347    pub fn create(name: &str) -> Self {
348        Self {
349            name: name.to_string(),
350            prompt: None,
351            types: HashMap::new(),
352            defaults: HashMap::new(),
353            dependencies: HashSet::new(),
354            reverse_dependencies: HashMap::new(),
355            weak_dependencies: HashMap::new(),
356            menu_dependencies: HashSet::new(),
357            range: None,
358            help: VecDeque::new(),
359        }
360    }
361}