formualizer_eval/engine/
sheet_registry.rs1use std::collections::HashMap;
2
3use crate::SheetId;
4
5#[derive(Default, Debug)]
6pub struct SheetRegistry {
7 id_by_name: HashMap<String, SheetId>,
8 name_by_id: Vec<String>,
9}
10
11impl SheetRegistry {
12 pub fn new() -> Self {
13 SheetRegistry::default()
14 }
15
16 pub fn id_for(&mut self, name: &str) -> SheetId {
17 if let Some(&id) = self.id_by_name.get(name) {
18 return id;
19 }
20
21 let id = self.name_by_id.len() as SheetId;
22 self.name_by_id.push(name.to_string());
23 self.id_by_name.insert(name.to_string(), id);
24 id
25 }
26
27 pub fn name(&self, id: SheetId) -> &str {
28 if (id as usize) < self.name_by_id.len() {
29 &self.name_by_id[id as usize]
30 } else {
31 ""
32 }
33 }
34
35 pub fn get_id(&self, name: &str) -> Option<SheetId> {
36 self.id_by_name.get(name).copied()
37 }
38
39 pub fn active_len(&self) -> usize {
41 self.name_by_id
42 .iter()
43 .filter(|name| !name.is_empty())
44 .count()
45 }
46
47 pub fn active_position_by_id(&self, id: SheetId) -> Option<usize> {
49 let idx = id as usize;
50 if idx >= self.name_by_id.len() || self.name_by_id[idx].is_empty() {
51 return None;
52 }
53 Some(
54 self.name_by_id
55 .iter()
56 .take(idx + 1)
57 .filter(|name| !name.is_empty())
58 .count(),
59 )
60 }
61
62 pub fn active_position(&self, name: &str) -> Option<usize> {
64 self.get_id(name)
65 .and_then(|id| self.active_position_by_id(id))
66 }
67
68 pub fn active_span_len(&self, first: &str, last: &str) -> Option<usize> {
70 let a = self.active_position(first)?;
71 let b = self.active_position(last)?;
72 Some(a.abs_diff(b) + 1)
73 }
74
75 pub fn all_sheets(&self) -> Vec<(SheetId, String)> {
77 self.name_by_id
78 .iter()
79 .enumerate()
80 .filter(|(_, name)| !name.is_empty())
81 .map(|(id, name)| (id as SheetId, name.clone()))
82 .collect()
83 }
84
85 pub fn remove(&mut self, id: SheetId) -> Result<(), formualizer_common::ExcelError> {
88 use formualizer_common::{ExcelError, ExcelErrorKind};
89
90 if id as usize >= self.name_by_id.len() {
92 return Err(
93 ExcelError::new(ExcelErrorKind::Value).with_message("Sheet ID does not exist")
94 );
95 }
96
97 let name = self.name_by_id[id as usize].clone();
99 if name.is_empty() {
100 return Ok(());
102 }
103
104 self.id_by_name.remove(&name);
106
107 self.name_by_id[id as usize] = String::new();
109
110 Ok(())
111 }
112
113 pub fn rename(
115 &mut self,
116 id: SheetId,
117 new_name: &str,
118 ) -> Result<(), formualizer_common::ExcelError> {
119 use formualizer_common::{ExcelError, ExcelErrorKind};
120
121 if id as usize >= self.name_by_id.len() {
123 return Err(
124 ExcelError::new(ExcelErrorKind::Value).with_message("Sheet ID does not exist")
125 );
126 }
127
128 let old_name = self.name_by_id[id as usize].clone();
130
131 if let Some(&existing_id) = self.id_by_name.get(new_name)
133 && existing_id != id
134 {
135 return Err(ExcelError::new(ExcelErrorKind::Value)
136 .with_message(format!("Sheet name '{new_name}' already exists")));
137 }
138
139 self.id_by_name.remove(&old_name);
141
142 self.name_by_id[id as usize] = new_name.to_string();
144 self.id_by_name.insert(new_name.to_string(), id);
145
146 Ok(())
147 }
148}