Skip to main content

tree_table/api/
tree_extend.rs

1use alloc::format;
2use alloc::rc::Rc;
3use alloc::string::String;
4use alloc::vec;
5use alloc::vec::Vec;
6use core::cell::RefCell;
7use hashbrown::HashMap;
8
9use crate::args::{CycleHandling, DuplicateIdHandling, EmptyIdHandling, TreeExtendArgs};
10use crate::str_err;
11use crate::types::extensions::TrySetExt;
12use crate::utils::consecutive_ranges::consecutive_ranges_owned;
13use crate::{Change, EventData, Header, IndexCell, MaxMap, NO_END, Table, TableCell, Val};
14
15#[inline]
16fn tree_extend_get_descendants<'a>(
17    tree: &'a HashMap<Rc<str>, IndexCell>,
18    initial_chn: &[Rc<str>],
19) -> impl Iterator<Item = Rc<str>> + 'a {
20    struct TreeDescendantIterator<'a> {
21        tree: &'a HashMap<Rc<str>, IndexCell>,
22        stack: Vec<Rc<str>>,
23    }
24
25    impl Iterator for TreeDescendantIterator<'_> {
26        type Item = Rc<str>;
27
28        fn next(&mut self) -> Option<Self::Item> {
29            self.stack.pop().map(|current| {
30                if let Some(cell) = self.tree.get(&current) {
31                    for child in cell.chn.iter().rev().cloned() {
32                        self.stack.push(child);
33                    }
34                }
35                current
36            })
37        }
38    }
39
40    let stack = initial_chn.iter().cloned().rev().collect::<Vec<_>>();
41    TreeDescendantIterator { tree, stack }
42}
43
44#[inline]
45fn tree_extend_check_inf_loop(
46    tree_map: &HashMap<Rc<str>, IndexCell>,
47    initial_chn: &[Rc<str>],
48    par: &str,
49) -> bool {
50    tree_extend_get_descendants(tree_map, initial_chn).any(|did| &*did == par)
51}
52
53impl Table {
54    /// Builds table cells for a given row specification, handling both provided values and inherited properties.
55    #[inline]
56    pub(crate) fn build_row_cells(
57        icells: &[IndexCell],
58        header: &Header,
59        vals: Option<Vec<(String, Val)>>,
60        inherit_row: usize,
61        do_inherit: bool,
62        empty_val: &Val,
63        ncols: usize,
64    ) -> Result<MaxMap<TableCell>, String> {
65        let mut cols_map: MaxMap<TableCell> = MaxMap::new();
66        if do_inherit {
67            let mut provided: Vec<Option<Val>> = vec![None; ncols];
68            if let Some(vals) = vals {
69                for (key, val) in vals.into_iter() {
70                    let cn = Self::acr_pos(&header.iid_to_col, &key)?;
71                    // Last value wins if duplicate positions
72                    provided.try_set(cn, Some(val))?;
73                }
74            }
75            for (cn, opt_val) in provided.into_iter().enumerate() {
76                let props = Self::acr_tcell_props(icells, inherit_row, cn).cloned();
77                if let Some(val) = opt_val {
78                    // Provided: set with inherited props (which may be None)
79                    cols_map.set_cell(cn, TableCell { val, props });
80                } else if props.is_some() {
81                    // Missing but has props: set with empty val
82                    cols_map.set_cell(
83                        cn,
84                        TableCell {
85                            val: empty_val.clone(),
86                            props,
87                        },
88                    );
89                }
90                // Otherwise: missing with no props -> skip
91            }
92        } else {
93            // Process cells provided by row_spec.vals
94            if let Some(vals) = vals {
95                for (key, val) in vals.into_iter() {
96                    let cn = Self::acr_pos(&header.iid_to_col, &key)?;
97                    cols_map.set_cell(cn, TableCell { val, props: None });
98                }
99            }
100        }
101        Ok(cols_map)
102    }
103
104    /// Extend the tree by adding new rows.
105    pub fn tree_extend(
106        &mut self,
107        kwargs: Option<TreeExtendArgs>,
108    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
109        let kwargs = kwargs.unwrap_or_default();
110        let empty_id_handling = kwargs.empty_ids;
111        let duplicate_id_handling = kwargs.duplicate_ids;
112        let cycle_handling = kwargs.cycles;
113        let check_for_cycles: bool = cycle_handling != CycleHandling::Ignore;
114        let mut tree_map: HashMap<Rc<str>, IndexCell> = HashMap::with_capacity(kwargs.rows.len());
115        let mut tops: Vec<Rc<str>> = Vec::with_capacity(kwargs.rows.len() / 2);
116        // parents added to the tree_map but which never have their own rows as iids
117        let mut par_stubs: HashMap<Rc<str>, Vec<Rc<str>>> = HashMap::new();
118        let empty_val: Val = self.opts.empty_val.clone();
119        let empty_ival: Val = self.opts.empty_index_val.clone();
120        let default_dim = self.cr_get_default_row_dim();
121        let mut event_data: EventData = self.cr_new_event(false);
122        let ncols = Self::acr_total_cols(&self.grid.header.cells);
123        let mut row_ctr = Self::acr_total_rows(&self.grid.index.cells);
124
125        // Determine which row to inherit cell props from
126        let opt_inherit_row =
127            self.cr_get_inherit_row(&self.grid.index.iid_to_row, row_ctr, &kwargs.inherit)?;
128        let do_inherit = opt_inherit_row.is_some();
129        let inherit_row = opt_inherit_row.unwrap_or(0);
130        let index_props = if do_inherit {
131            self.grid.index.clone_props(&inherit_row)
132        } else {
133            None
134        };
135
136        // Iterate through the array elements
137        for mut row_spec in kwargs.rows.into_iter() {
138            // We're effectively taking row_spec.iid here
139            let iid: Rc<str> = if row_spec.iid.is_empty() {
140                match empty_id_handling {
141                    EmptyIdHandling::Error => {
142                        return Err(str_err!(
143                            "Empty iid. Parent: {:?}, Text: {:?}, Values: {:?}",
144                            row_spec.par,
145                            row_spec.val,
146                            row_spec.vals
147                        ));
148                    }
149                    EmptyIdHandling::Ignore => {
150                        continue;
151                    }
152                    EmptyIdHandling::New => {
153                        // new_iid() guarantees a new id
154                        let mut new = self.grid.index.new_iid()?;
155                        while tree_map.contains_key(new.as_str()) {
156                            new = self.grid.index.new_iid()?;
157                        }
158                        Rc::from(new)
159                    }
160                }
161            // iid should not already be in Table
162            } else if self
163                .grid
164                .index
165                .iid_to_row
166                .contains_key(row_spec.iid.as_str())
167            {
168                match duplicate_id_handling {
169                    DuplicateIdHandling::Error => {
170                        return Err(str_err!("iid already exists: {}", row_spec.iid));
171                    }
172                    DuplicateIdHandling::Rename => {
173                        let mut n: u64 = 1;
174                        let iid = row_spec.iid.as_str();
175                        let mut new = format!("{iid}_{n}");
176                        while self.grid.index.iid_to_row.contains_key(new.as_str()) {
177                            n += 1;
178                            new = format!("{iid}_{n}");
179                        }
180                        Rc::from(new)
181                    }
182                }
183            } else {
184                Rc::from(row_spec.iid)
185            };
186
187            let mut par: Rc<str> = Rc::from(row_spec.par);
188            // par should not already be in Table
189            if self.grid.index.iid_to_row.contains_key(&par) {
190                match duplicate_id_handling {
191                    DuplicateIdHandling::Error => {
192                        return Err(str_err!("parent already exists: {}", par));
193                    }
194                    DuplicateIdHandling::Rename => {
195                        let mut n: u64 = 1;
196                        let mut new = format!("{par}_{n}");
197                        while self.grid.index.iid_to_row.contains_key(new.as_str()) {
198                            n += 1;
199                            new = format!("{par}_{n}");
200                        }
201                        par = Rc::from(new);
202                    }
203                }
204            }
205
206            // Check for duplicate iids in rows
207            let iid = if tree_map.contains_key(&iid) {
208                match duplicate_id_handling {
209                    DuplicateIdHandling::Error => {
210                        return Err(str_err!("iid is a duplicate in rows: {}", iid));
211                    }
212                    DuplicateIdHandling::Rename => {
213                        let mut n: u64 = 1;
214                        let mut new = format!("{iid}_{n}");
215                        // Have to check a 2nd time if iid_to_row contains newly renamed iid
216                        while tree_map.contains_key(new.as_str())
217                            || self.grid.index.iid_to_row.contains_key(new.as_str())
218                        {
219                            n += 1;
220                            new = format!("{iid}_{n}");
221                        }
222                        Rc::from(new)
223                    }
224                }
225            } else {
226                iid
227            };
228
229            let mut new_icell = IndexCell {
230                iid: iid.clone(),
231                val: row_spec.val.unwrap_or(empty_ival.clone()),
232                vals: Self::build_row_cells(
233                    &self.grid.index.cells,
234                    &self.grid.header,
235                    row_spec.vals.take(),
236                    inherit_row,
237                    do_inherit,
238                    &empty_val,
239                    ncols,
240                )?,
241                dim: row_spec.dim.unwrap_or(default_dim),
242                vis: false,
243                par: self.grid.index.empty_par.clone(),
244                chn: Vec::new(),
245                open: row_spec.open,
246                props: index_props.clone(),
247            };
248
249            // If it is an existing stub, remove it from stubs and
250            // xfer the stubs chn to the icell
251            // (No need to transfer pending children pars here; defer to DFS)
252            if let Some(pending_chn) = par_stubs.remove(&iid) {
253                new_icell.chn = pending_chn;
254            }
255
256            // Check for cycles (inf loops of children) and id-parent equality
257            if iid == par {
258                match cycle_handling {
259                    CycleHandling::Error => {
260                        return Err(str_err!("iid: {iid} equal to parent"));
261                    }
262                    CycleHandling::Skip => {
263                        continue;
264                    }
265                    CycleHandling::OnlyPrior => {
266                        break;
267                    }
268                    _ => par = self.grid.index.empty_par.clone(),
269                }
270            }
271            if check_for_cycles {
272                let inf_loop =
273                    tree_extend_check_inf_loop(&tree_map, new_icell.chn.as_slice(), &par);
274                if inf_loop {
275                    match cycle_handling {
276                        CycleHandling::Error => {
277                            return Err(str_err!(
278                                "Cycle detected for iid: {} with parent: {}",
279                                iid,
280                                par
281                            ));
282                        }
283                        CycleHandling::Skip => {
284                            continue;
285                        }
286                        CycleHandling::Clear => {
287                            par = self.grid.index.empty_par.clone();
288                        }
289                        CycleHandling::OnlyPrior => {
290                            break;
291                        }
292                        CycleHandling::Ignore => unreachable!(),
293                    }
294                }
295            }
296
297            // Finally, deal with parent and add icell
298            if !par.is_empty() {
299                if let Some(par_cell) = tree_map.get_mut(&par) {
300                    // Parent is already an iid in tree
301                    // - Set icell parent
302                    // - Add icell to parents chn
303                    new_icell.par = par;
304                    par_cell.chn.push(iid.clone());
305                } else {
306                    // Parent is not already an iid in tree
307                    // Append icell to par_stubs under par iid
308                    // All chn under par iid stubs (including new_icell)
309                    // will have to have .par updated later
310                    par_stubs
311                        .entry(par)
312                        .or_insert_with(Vec::new)
313                        .push(iid.clone());
314                }
315            } else {
316                new_icell.vis = true;
317                tops.push(iid.clone());
318            }
319            tree_map.insert(iid, new_icell);
320        }
321
322        // Drain remaining stub ids into tree_map as top-level with defaults
323        for (iid, chn) in par_stubs.into_iter() {
324            let cols_map = Self::build_row_cells(
325                &self.grid.index.cells,
326                &self.grid.header,
327                None,
328                inherit_row,
329                do_inherit,
330                &empty_val,
331                ncols,
332            )?;
333            let stub = IndexCell {
334                iid: iid.clone(),
335                val: empty_ival.clone(),
336                vals: cols_map,
337                dim: default_dim,
338                vis: true,
339                par: self.grid.index.empty_par.clone(),
340                chn,
341                open: false,
342                props: index_props.clone(),
343            };
344            // (No need to update child pars here; defer to DFS)
345            tops.push(iid.clone());
346            tree_map.insert(iid, stub);
347        }
348
349        // Return early without modifying existing table if no rows are to be added
350        if tree_map.is_empty() {
351            return Err(str_err!("No rows to be added"));
352        }
353
354        let orig_disp_len = self.grid.disp_rows.len();
355        let orig_canvas_len = self.grid.canvas_rows.len();
356        let orig_index_cells_len = self.grid.index.cells.len();
357        // Iterate over index cells from truncate point, remove the iids from iid_to_row
358
359        let mut sorted_seq: Vec<usize> = Vec::with_capacity(tree_map.len());
360
361        // self.cr_remake_rows()
362        let mut acc: u64 = self.grid.canvas_rows.last().cloned().unwrap_or(0);
363        let mut stack: Vec<(Rc<str>, bool, Rc<str>)> = Vec::with_capacity(100);
364        self.grid.index.cells.reserve(tree_map.len());
365        self.grid.index.iid_to_row.reserve(tree_map.len());
366
367        let mut_result: Result<(), String> = (|| -> Result<(), String> {
368            for top in tops.into_iter() {
369                sorted_seq.push(row_ctr);
370                let icell = tree_map
371                    .remove(&top)
372                    .ok_or_else(|| str_err!("IndexCell: {} not found in tree_map", top))?;
373                let child_vis = icell.open;
374                for child in icell.chn.iter().rev().cloned() {
375                    stack.push((child, child_vis, top.clone()));
376                }
377                self.grid.disp_rows.push(row_ctr);
378                acc += icell.dim;
379                self.grid.canvas_rows.push(acc);
380                self.grid.index.push_row(row_ctr, icell.iid.clone(), icell);
381                row_ctr += 1;
382
383                while let Some((not_top, inherited_vis, par_iid)) = stack.pop() {
384                    sorted_seq.push(row_ctr);
385                    let mut icell = tree_map
386                        .remove(&not_top)
387                        .ok_or_else(|| str_err!("IndexCell: {} not found in tree_map", not_top))?;
388                    icell.par = par_iid;
389                    icell.vis = inherited_vis;
390                    let child_vis = inherited_vis && icell.open;
391                    for child in icell.chn.iter().rev().cloned() {
392                        stack.push((child, child_vis, not_top.clone()));
393                    }
394                    // Row grid lines, self.cr_remake_rows()
395                    if inherited_vis {
396                        self.grid.disp_rows.push(row_ctr);
397                        acc += icell.dim;
398                        self.grid.canvas_rows.push(acc);
399                    }
400                    // Push cell to index, self.grid.index.add_rows()
401                    self.grid.index.push_row(row_ctr, icell.iid.clone(), icell);
402                    row_ctr += 1;
403                }
404            }
405            Ok(())
406        })();
407
408        if let Err(e) = mut_result {
409            self.grid.disp_rows.truncate(orig_disp_len);
410            self.grid.canvas_rows.truncate(orig_canvas_len);
411            for cell in &self.grid.index.cells[orig_index_cells_len..] {
412                self.grid.index.iid_to_row.remove(&cell.iid);
413            }
414            self.grid.index.cells.truncate(orig_index_cells_len);
415            return Err(e);
416        }
417
418        // Select the added rows
419        if kwargs.select {
420            Self::acr_deselect_all(
421                &mut self.sel,
422                if kwargs.save_selection {
423                    Some(&mut event_data)
424                } else {
425                    None
426                },
427            );
428            for (start, end) in consecutive_ranges_owned(
429                sorted_seq
430                    .iter()
431                    .filter_map(|n| Self::acr_data_to_disp_opt(&self.grid.disp_rows, *n)),
432            ) {
433                Self::acr_add_selection_box(&mut self.sel, &self.grid, start, end, 0, NO_END, true);
434            }
435            if kwargs.save_selection {
436                event_data.changes.push(Change::add_selection_boxes(
437                    self.sel.selection_boxes.len(),
438                    None,
439                ));
440            }
441        }
442
443        event_data.changes.push(Change::AddRows(sorted_seq));
444        self.cr_finalize_event(event_data, kwargs.undo, kwargs.emit)
445    }
446}