papergrid/config/spanned/
entity_map.rs1use std::collections::HashMap;
2
3use fnv::FnvHashMap;
4
5use crate::config::{Entity, Position};
6
7#[derive(Debug, Default, Clone, PartialEq, Eq)]
9pub struct EntityMap<T> {
10 global: T,
13 columns: FnvHashMap<usize, T>,
14 rows: FnvHashMap<usize, T>,
15 cells: FnvHashMap<Position, T>,
16}
17
18impl<T> EntityMap<T> {
19 pub fn new(global: T) -> Self {
21 Self {
22 global,
23 rows: Default::default(),
24 columns: Default::default(),
25 cells: Default::default(),
26 }
27 }
28
29 pub fn is_empty(&self) -> bool {
31 self.columns.is_empty() && self.rows.is_empty() && self.cells.is_empty()
32 }
33
34 pub fn get(&self, pos: Position) -> &T {
36 self.cells
54 .get(&pos)
55 .or_else(|| self.columns.get(&pos.col))
56 .or_else(|| self.rows.get(&pos.row))
57 .unwrap_or(&self.global)
58 }
59
60 pub fn remove(&mut self, entity: Entity) {
62 match entity {
63 Entity::Global => {
64 self.cells.clear();
65 self.rows.clear();
66 self.columns.clear();
67 }
68 Entity::Column(col) => self.cells.retain(|pos, _| pos.col != col),
69 Entity::Row(row) => self.cells.retain(|pos, _| pos.row != row),
70 Entity::Cell(row, col) => {
71 self.cells.remove(&Position::new(row, col));
72 }
73 }
74 }
75}
76
77impl<T: Clone> EntityMap<T> {
78 pub fn insert(&mut self, entity: Entity, value: T) {
80 match entity {
81 Entity::Column(col) => {
82 for &row in self.rows.keys() {
83 self.cells.insert(Position::new(row, col), value.clone());
84 }
85
86 self.columns.insert(col, value);
87 }
88 Entity::Row(row) => {
89 for &col in self.columns.keys() {
90 self.cells.insert(Position::new(row, col), value.clone());
91 }
92
93 self.rows.insert(row, value);
94 }
95 Entity::Cell(row, col) => {
96 self.cells.insert(Position::new(row, col), value);
97 }
98 Entity::Global => {
99 self.remove(Entity::Global);
100 self.global = value
101 }
102 }
103 }
104}
105
106impl<T> From<EntityMap<T>> for HashMap<Entity, T> {
107 fn from(value: EntityMap<T>) -> Self {
108 let mut m = HashMap::new();
109 m.insert(Entity::Global, value.global);
110
111 for (pos, value) in value.cells {
112 m.insert(Entity::from(pos), value);
113 }
114
115 for (row, value) in value.rows {
116 m.insert(Entity::Row(row), value);
117 }
118
119 for (col, value) in value.columns {
120 m.insert(Entity::Column(col), value);
121 }
122
123 m
124 }
125}
126
127impl<T> AsRef<T> for EntityMap<T> {
128 fn as_ref(&self) -> &T {
129 &self.global
130 }
131}