dwfv/signaldb/
scope.rs

1// SPDX-License-Identifier: MIT
2use super::signal::Signal;
3use std::collections::{BTreeMap, BTreeSet};
4
5#[derive(Debug)]
6pub enum ScopeChild {
7    Signal,
8    Scope,
9}
10
11#[derive(Debug)]
12pub struct Scope {
13    pub name: String,
14    signals: BTreeSet<String>,
15    scopes: BTreeMap<String, Scope>,
16    path: Vec<String>,
17}
18
19impl Scope {
20    pub fn new(name: String) -> Scope {
21        Scope {
22            name,
23            signals: BTreeSet::new(),
24            scopes: BTreeMap::new(),
25            path: Vec::new(),
26        }
27    }
28
29    pub fn add_scope(&mut self, path: &[&str]) {
30        if let Some(name) = path.first() {
31            match self.scopes.get(*name) {
32                Some(_) => self.get_scope(name).unwrap().add_scope(&path[1..]),
33                None => {
34                    let mut s = Scope::new(name.to_string());
35                    s.path = self.path.clone();
36                    s.path.push(self.name.clone());
37                    s.add_scope(&path[1..]);
38                    self.scopes.insert(s.name.clone(), s);
39                }
40            }
41        }
42    }
43
44    pub fn get_scope(&mut self, name: &str) -> Option<&mut Scope> {
45        self.scopes.get_mut(name)
46    }
47
48    pub fn get_scope_by_path(&mut self, path: &[&str]) -> Option<&mut Scope> {
49        match path.first() {
50            Some(name) => match self.scopes.get(*name) {
51                Some(_) => self.get_scope(name).unwrap().get_scope_by_path(&path[1..]),
52                None => None,
53            },
54            None => Some(self),
55        }
56    }
57
58    pub fn add_signal(&mut self, signal: &mut Signal) {
59        self.signals.insert(signal.id.clone());
60        signal.path = self.path.clone();
61        signal.path.push(self.name.clone())
62    }
63
64    fn _traverse<T, F: FnMut(&str, &ScopeChild, u64) -> T>(&self, depth: u64, f: &mut F) {
65        for name in &self.signals {
66            f(name, &ScopeChild::Signal, depth);
67        }
68
69        for (name, scope) in &self.scopes {
70            f(name, &ScopeChild::Scope, depth);
71            scope._traverse(depth + 1, f);
72        }
73    }
74
75    pub fn traverse<T, F: FnMut(&str, &ScopeChild, u64) -> T>(&self, f: &mut F) {
76        self._traverse(0, f)
77    }
78}
79
80#[cfg(test)]
81mod test {
82    use super::*;
83
84    #[test]
85    fn scope() {
86        let mut s = Scope::new(String::from("top"));
87        s.add_scope(&["foo", "bar"]);
88
89        let foo = s.get_scope_by_path(&["foo"]).expect("Path doesn't exist");
90        foo.add_signal(&mut Signal::new("bar", "bar", 42));
91
92        s.get_scope_by_path(&["foo", "bar"])
93            .expect("Path doesn't exist");
94    }
95}