use std::collections::HashMap;
use crate::SheetId;
#[derive(Default, Debug)]
pub struct SheetRegistry {
id_by_name: HashMap<String, SheetId>,
name_by_id: Vec<String>,
}
impl SheetRegistry {
pub fn new() -> Self {
SheetRegistry::default()
}
pub fn id_for(&mut self, name: &str) -> SheetId {
if let Some(&id) = self.id_by_name.get(name) {
return id;
}
let id = self.name_by_id.len() as SheetId;
self.name_by_id.push(name.to_string());
self.id_by_name.insert(name.to_string(), id);
id
}
pub fn name(&self, id: SheetId) -> &str {
if (id as usize) < self.name_by_id.len() {
&self.name_by_id[id as usize]
} else {
""
}
}
pub fn get_id(&self, name: &str) -> Option<SheetId> {
self.id_by_name.get(name).copied()
}
pub fn active_len(&self) -> usize {
self.name_by_id
.iter()
.filter(|name| !name.is_empty())
.count()
}
pub fn active_position_by_id(&self, id: SheetId) -> Option<usize> {
let idx = id as usize;
if idx >= self.name_by_id.len() || self.name_by_id[idx].is_empty() {
return None;
}
Some(
self.name_by_id
.iter()
.take(idx + 1)
.filter(|name| !name.is_empty())
.count(),
)
}
pub fn active_position(&self, name: &str) -> Option<usize> {
self.get_id(name)
.and_then(|id| self.active_position_by_id(id))
}
pub fn active_span_len(&self, first: &str, last: &str) -> Option<usize> {
let a = self.active_position(first)?;
let b = self.active_position(last)?;
Some(a.abs_diff(b) + 1)
}
pub fn all_sheets(&self) -> Vec<(SheetId, String)> {
self.name_by_id
.iter()
.enumerate()
.filter(|(_, name)| !name.is_empty())
.map(|(id, name)| (id as SheetId, name.clone()))
.collect()
}
pub fn remove(&mut self, id: SheetId) -> Result<(), formualizer_common::ExcelError> {
use formualizer_common::{ExcelError, ExcelErrorKind};
if id as usize >= self.name_by_id.len() {
return Err(
ExcelError::new(ExcelErrorKind::Value).with_message("Sheet ID does not exist")
);
}
let name = self.name_by_id[id as usize].clone();
if name.is_empty() {
return Ok(());
}
self.id_by_name.remove(&name);
self.name_by_id[id as usize] = String::new();
Ok(())
}
pub fn rename(
&mut self,
id: SheetId,
new_name: &str,
) -> Result<(), formualizer_common::ExcelError> {
use formualizer_common::{ExcelError, ExcelErrorKind};
if id as usize >= self.name_by_id.len() {
return Err(
ExcelError::new(ExcelErrorKind::Value).with_message("Sheet ID does not exist")
);
}
let old_name = self.name_by_id[id as usize].clone();
if let Some(&existing_id) = self.id_by_name.get(new_name)
&& existing_id != id
{
return Err(ExcelError::new(ExcelErrorKind::Value)
.with_message(format!("Sheet name '{new_name}' already exists")));
}
self.id_by_name.remove(&old_name);
self.name_by_id[id as usize] = new_name.to_string();
self.id_by_name.insert(new_name.to_string(), id);
Ok(())
}
}