tree_table/types/
header.rs1use crate::CellProps;
2use crate::HeaderCell;
3use crate::str_err;
4use crate::types::CyclingCounter;
5use crate::utils::utils_fns::n_to_base62;
6use crate::utils::utils_fns::pull_n;
7use crate::utils::utils_fns::push_n_add;
8use alloc::rc::Rc;
9use alloc::string::String;
10use alloc::vec::Vec;
11use hashbrown::HashMap;
12
13#[derive(Clone, Debug)]
14pub struct Header {
15 pub iid_to_col: HashMap<Rc<str>, usize>,
16 pub cells: Vec<HeaderCell>,
17 pub iid_ctr: CyclingCounter,
18}
19
20impl Header {
21 pub fn new() -> Self {
22 Header {
23 iid_to_col: HashMap::new(),
24 cells: Vec::new(),
25 iid_ctr: CyclingCounter::new(),
26 }
27 }
28
29 pub fn reset(&mut self) {
31 self.iid_to_col.clear();
32 self.cells.clear();
33 self.iid_ctr = CyclingCounter::new();
34 }
35
36 pub fn clone_props(&self, col: &usize) -> Option<CellProps> {
38 self.cells.get(*col).and_then(|cell| cell.props.clone())
39 }
40
41 pub fn get_props(&self, col: &usize) -> Option<&CellProps> {
43 self.cells.get(*col).and_then(|cell| cell.props.as_ref())
44 }
45
46 pub fn add_cols(&mut self, to_add: Vec<(usize, HeaderCell)>) {
48 for (_, col) in self.iid_to_col.iter_mut() {
50 *col = push_n_add(*col, &to_add);
51 }
52 for (pos, val) in to_add.into_iter() {
54 self.iid_to_col.insert(val.iid.clone(), pos.clone());
55 self.cells.insert(pos, val);
56 }
57 }
58
59 pub fn del_cols(&mut self, sorted_seq: &[usize]) -> Result<Vec<(usize, HeaderCell)>, String> {
61 let largest_pos = *sorted_seq
62 .last()
63 .ok_or_else(|| str_err!("To delete is empty."))?;
64 if largest_pos >= self.cells.len() {
65 return Err(str_err!(
66 "Deletion pos: {} out of bounds of header len: {}",
67 largest_pos,
68 self.cells.len()
69 ));
70 }
71 let mut removed = Vec::with_capacity(sorted_seq.len());
72 for (i, &pos) in sorted_seq.iter().enumerate() {
73 let cell = self.cells.remove(pos - i);
74 self.iid_to_col.remove(&cell.iid);
75 removed.push((pos, cell));
76 }
77 for (_, pos) in self.iid_to_col.iter_mut() {
79 *pos = pull_n(*pos, sorted_seq);
80 }
81 Ok(removed)
82 }
83
84 pub fn move_cols(&mut self, full_new_to_old: &[usize]) -> Result<(), String> {
85 let n = self.cells.len();
86 if n == 0 {
87 return Ok(());
88 }
89 if full_new_to_old.len() != n {
90 return Err(str_err!(
91 "move_cols: length mismatch (got {}, expected {})",
92 full_new_to_old.len(),
93 n
94 ));
95 }
96
97 #[cfg(any(debug_assertions, feature = "safety"))]
98 {
99 use alloc::vec;
100
101 let mut seen = vec![false; n];
102 for &old_idx in full_new_to_old {
103 if old_idx >= n || seen[old_idx] {
104 return Err(str_err!("Mapping error: invalid old index {}", old_idx));
105 }
106 seen[old_idx] = true;
107 }
108 }
109
110 let mut old_cells = core::mem::take(&mut self.cells)
111 .into_iter()
112 .map(Some)
113 .collect::<Vec<_>>();
114
115 self.cells = Vec::with_capacity(n);
116
117 for (new_idx, &old_idx) in full_new_to_old.iter().enumerate() {
118 let cell = old_cells
119 .get_mut(old_idx)
120 .and_then(Option::take)
121 .ok_or_else(|| str_err!("Mapping error: invalid or duplicate index {}", old_idx))?;
122
123 if let Some(col) = self.iid_to_col.get_mut(&cell.iid) {
124 *col = new_idx; }
126 self.cells.push(cell);
127 }
128
129 Ok(())
130 }
131
132 #[inline]
133 pub fn new_iid(&mut self) -> Result<String, String> {
134 let mut iid = n_to_base62(
135 self.iid_ctr
136 .next()
137 .ok_or_else(|| str_err!("Cycling counter should never end"))?,
138 );
139 if self.iid_to_col.contains_key(iid.as_str()) {
140 let mut cycles: usize = 0;
141 while self.iid_to_col.contains_key(iid.as_str()) {
142 if cycles == usize::MAX {
143 return Err(str_err!("Column limit reached."));
144 }
145 iid = n_to_base62(
146 self.iid_ctr
147 .next()
148 .ok_or_else(|| str_err!("Cycling counter should never end"))?,
149 );
150 cycles = cycles.saturating_add(1);
151 }
152 }
153 Ok(iid)
154 }
155}