elm_parser/counter/
counters.rs1use crate::datacell::{Datacell::*, ElementCell::Prop};
2
3use super::{
4 counter_commands::CommandType, counter_instance::CounterInstance, counter_types::CounterType,
5 handle_instance::HandleInstance,
6};
7
8#[derive(Debug, Clone)]
9pub struct Counters {
10 pub counters_list: Vec<CounterInstance>,
11 pub handles_list: Vec<HandleInstance>,
12}
13
14impl Counters {
18 pub fn new() -> Counters {
19 Counters {
20 counters_list: Vec::new(),
21 handles_list: Vec::new(),
22 }
23 }
24
25 fn iter_props(&mut self, json: &DataCell, props: &Vec<Prop>) {
26 props.iter().for_each(|prop| {
27 if CounterType::is_valid(&prop.key) {
28 let mut value_splits = prop.value.split(" ");
29 let counter_name = value_splits.next().expect("Counter must have a name");
30
31 let default_value = value_splits.next();
32 self.add_counter(CounterInstance::new(
34 counter_name,
35 &prop.key,
36 json.id,
37 default_value,
38 ));
39 }
40 })
41 }
42
43 pub fn get_counters_from_json(&mut self, json: &DataCell) {
44 match &json.cell_type {
45 CellType::Element(el) => {
46 self.iter_props(json, &el.props);
47 el.children
48 .iter()
49 .for_each(|child| self.get_counters_from_json(child))
50 }
51 CellType::Root(root) => root
52 .children
53 .iter()
54 .for_each(|child| self.get_counters_from_json(child)),
55 _ => (),
56 }
57 }
58
59 pub fn add_counter(&mut self, counter: CounterInstance) {
60 let counter_exists = self.counters_list.iter().any(|c| c.name == counter.name);
61 assert!(
62 !counter_exists,
63 "Counter name {} already used",
64 counter.name
65 );
66 self.counters_list.push(counter);
67 }
68
69 pub fn add_handle(&mut self, handle: HandleInstance) {
70 let handle_exists = self.handles_list.iter().any(|c| c.name == handle.name);
71 assert!(!handle_exists, "handle {} already assigned", handle.name);
72 self.handles_list.push(handle);
73 }
74
75 pub fn remove_counter(&mut self, counter: &CounterInstance) {
76 self.counters_list = self
77 .counters_list
78 .iter()
79 .filter(|c| c.name != counter.name)
80 .cloned()
81 .collect();
82 }
83
84 pub fn execute(
85 &mut self,
86 command_type: CommandType,
87 counter_name: &str,
88 handle_name: &Option<String>,
89 ) -> Option<String> {
90 let counter = self
91 .counters_list
92 .iter_mut()
93 .find(|c| c.name == counter_name);
94 assert!(
95 !counter.is_none(),
96 "Counter {counter_name} Does not exist or is out of scope"
97 );
98
99 match command_type {
100 CommandType::INC => counter.unwrap().increment(),
101 CommandType::DEC => counter.unwrap().decrement(),
102 CommandType::ASSIGN => {
103 if let Some(handle_name) = handle_name {
104 let handle_exists = self.handles_list.iter().any(|c| &c.name == handle_name);
105 assert!(!handle_exists, "handle {} already assigned", handle_name);
106 self.handles_list.push(HandleInstance {
107 name: handle_name.to_string(),
108 value: counter.unwrap().current_value.to_string(),
109 });
110 }
111 }
112 CommandType::INSERT => {
113 return Some(counter.unwrap().current_value.to_string());
114 }
115 }
116 None
117 }
118
119 pub fn check_scope(&self, block_cell: &DataCell, counter_name: &str, json_tree: &DataCell) {
120 let counter = self.counters_list.iter().find(|c| c.name == counter_name);
121 assert!(
122 !counter.is_none(),
123 "Counter {counter_name} Does not exist or is out of scope"
124 );
125
126 let mut parents_list = Vec::new();
128 self.search_el(block_cell, json_tree, &mut parents_list);
129
130 assert!(
131 parents_list.contains(&counter.unwrap().scope),
132 "Counter {counter_name} is out of scope"
133 );
134 }
135
136 fn search_el(
137 &self,
138 block_cell: &DataCell,
139 json_tree: &DataCell,
140 parents_list: &mut Vec<usize>,
141 ) -> bool {
142 match &json_tree.cell_type {
143 CellType::Block(_) => json_tree.id == block_cell.id,
144 CellType::Element(el) => {
145 parents_list.push(json_tree.id.try_into().unwrap());
146
147 for child in el.children.iter() {
148 if self.search_el(block_cell, child, parents_list) {
149 return true;
150 }
151 }
152
153 parents_list.pop();
154 return false;
155 }
156 CellType::Root(el) => {
157 parents_list.push(json_tree.id.try_into().unwrap());
158
159 for child in el.children.iter() {
160 if self.search_el(block_cell, child, parents_list) {
161 return true;
162 }
163 }
164
165 parents_list.pop();
166 return false;
167 }
168 _ => false,
169 }
170 }
171}