use crate::types::Handle;
use indexmap::IndexMap;
pub mod layer;
pub mod linetype;
pub mod textstyle;
pub mod block_record;
pub mod dimstyle;
pub mod appid;
pub mod view;
pub mod vport;
pub mod ucs;
pub use layer::{Layer, LayerFlags};
pub use linetype::{LineType, LineTypeElement};
pub use textstyle::{TextStyle, TextGenerationFlags};
pub use block_record::BlockRecord;
pub use dimstyle::DimStyle;
pub use appid::AppId;
pub use view::View;
pub use vport::VPort;
pub use ucs::Ucs;
pub trait TableEntry {
fn handle(&self) -> Handle;
fn set_handle(&mut self, handle: Handle);
fn name(&self) -> &str;
fn set_name(&mut self, name: String);
fn is_standard(&self) -> bool {
false
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Table<T: TableEntry> {
entries: IndexMap<String, T>,
handle: Handle,
}
impl<T: TableEntry> Table<T> {
pub fn new() -> Self {
Table {
entries: IndexMap::new(),
handle: Handle::NULL,
}
}
pub fn with_handle(handle: Handle) -> Self {
Table {
entries: IndexMap::new(),
handle,
}
}
pub fn handle(&self) -> Handle {
self.handle
}
pub fn set_handle(&mut self, handle: Handle) {
self.handle = handle;
}
pub fn add(&mut self, entry: T) -> Result<(), String> {
let name = entry.name().to_uppercase();
if self.entries.contains_key(&name) {
return Err(format!("Entry '{}' already exists in table", entry.name()));
}
self.entries.insert(name, entry);
Ok(())
}
pub fn add_or_replace(&mut self, entry: T) {
let name = entry.name().to_uppercase();
self.entries.insert(name, entry);
}
pub fn get(&self, name: &str) -> Option<&T> {
self.entries.get(&name.to_uppercase())
}
pub fn get_mut(&mut self, name: &str) -> Option<&mut T> {
self.entries.get_mut(&name.to_uppercase())
}
pub fn remove(&mut self, name: &str) -> Option<T> {
self.entries.shift_remove(&name.to_uppercase())
}
pub fn contains(&self, name: &str) -> bool {
self.entries.contains_key(&name.to_uppercase())
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.entries.values()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
self.entries.values_mut()
}
pub fn names(&self) -> impl Iterator<Item = &str> {
self.entries.values().map(|e| e.name())
}
pub fn clear(&mut self) {
self.entries.clear();
}
}
impl<T: TableEntry> Default for Table<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, Clone)]
struct MockEntry {
handle: Handle,
name: String,
}
impl TableEntry for MockEntry {
fn handle(&self) -> Handle {
self.handle
}
fn set_handle(&mut self, handle: Handle) {
self.handle = handle;
}
fn name(&self) -> &str {
&self.name
}
fn set_name(&mut self, name: String) {
self.name = name;
}
}
#[test]
fn test_table_add_and_get() {
let mut table = Table::new();
let entry = MockEntry {
handle: Handle::new(1),
name: "Test".to_string(),
};
assert!(table.add(entry).is_ok());
assert!(table.contains("Test"));
assert!(table.contains("test")); assert_eq!(table.len(), 1);
}
#[test]
fn test_table_duplicate_entry() {
let mut table = Table::new();
let entry1 = MockEntry {
handle: Handle::new(1),
name: "Test".to_string(),
};
let entry2 = MockEntry {
handle: Handle::new(2),
name: "test".to_string(), };
assert!(table.add(entry1).is_ok());
assert!(table.add(entry2).is_err()); }
#[test]
fn test_table_remove() {
let mut table = Table::new();
let entry = MockEntry {
handle: Handle::new(1),
name: "Test".to_string(),
};
table.add(entry).unwrap();
assert_eq!(table.len(), 1);
let removed = table.remove("test");
assert!(removed.is_some());
assert_eq!(table.len(), 0);
}
}