1use super::event::Event;
5use super::event::EventLog;
6use super::*;
7use crate::error::{Error, Result};
8use crate::{HStore, Storable};
9use std::collections::{BTreeMap, HashMap};
10use std::fmt::Debug;
11use std::path::Path;
12use std::path::PathBuf;
13
14use std::ops::Deref;
15use std::ops::Index;
16use std::sync::{Arc, RwLock};
17
18#[derive(Debug, Clone, Hash)]
26pub struct XvcStore<T>
27where
28 T: Storable,
29{
30 map: BTreeMap<XvcEntity, T>,
31 entity_index: BTreeMap<T, Vec<XvcEntity>>,
32 previous: EventLog<T>,
33 current: EventLog<T>,
34}
35
36pub type SharedXStore<T> = Arc<RwLock<XvcStore<T>>>;
38
39impl<T> Deref for XvcStore<T>
40where
41 T: Storable,
42{
43 type Target = BTreeMap<XvcEntity, T>;
44
45 fn deref(&self) -> &Self::Target {
46 &self.map
47 }
48}
49
50impl<T> Index<&XvcEntity> for XvcStore<T>
51where
52 T: Storable,
53{
54 type Output = T;
55
56 fn index(&self, entity: &XvcEntity) -> &Self::Output {
57 self.map.index(entity)
58 }
59}
60
61impl<T> Default for XvcStore<T>
62where
63 T: Storable,
64{
65 fn default() -> Self {
66 Self::new()
67 }
68}
69
70impl<T> XvcStore<T>
71where
72 T: Storable,
73{
74 pub fn new() -> Self {
76 Self::from_event_logs(EventLog::<T>::new(), EventLog::<T>::new())
77 }
78
79 pub fn from_event_logs(previous: EventLog<T>, current: EventLog<T>) -> Self {
87 let map = Self::build_map(&previous, ¤t);
88 let entity_index = Self::build_index(&map);
89 Self {
90 map,
91 entity_index,
92 previous,
93 current,
94 }
95 }
96
97 pub fn all_event_log_for_entity(&self, entity: XvcEntity) -> Result<EventLog<T>> {
99 let mut prev_events = Self::filter_event_log_by_entity(&self.previous, entity)?;
100 let mut current_events = Self::filter_event_log_by_entity(&self.current, entity)?;
101 prev_events.append(&mut current_events);
102 Ok(EventLog::from_events(prev_events))
103 }
104
105 pub fn previous_event_log_for_entity(&self, entity: XvcEntity) -> Result<EventLog<T>> {
109 Ok(EventLog::from_events(Self::filter_event_log_by_entity(
110 &self.previous,
111 entity,
112 )?))
113 }
114
115 fn filter_event_log_by_entity(event_log: &EventLog<T>, xe: XvcEntity) -> Result<Vec<Event<T>>> {
116 let events = event_log
117 .iter()
118 .filter_map(|e| match e {
119 event @ Event::Add { entity, .. } => {
120 if *entity == xe {
121 Some(event.clone())
122 } else {
123 None
124 }
125 }
126 event @ Event::Remove { entity } => {
127 if *entity == xe {
128 Some(event.clone())
129 } else {
130 None
131 }
132 }
133 })
134 .collect();
135 Ok(events)
136 }
137
138 pub fn insert(&mut self, entity: XvcEntity, value: T) -> Option<T> {
144 self.current.push_event(Event::Add {
145 entity,
146 value: value.clone(),
147 });
148
149 match self.entity_index.get_mut(&value) {
150 Some(v) => {
151 v.push(entity);
152 }
153 None => {
154 self.entity_index.insert(value.clone(), vec![entity]);
155 }
156 }
157 self.map.insert(entity, value)
158 }
159
160 pub fn update(&mut self, entity: XvcEntity, value: T) -> Option<T> {
165 if self.map.contains_key(&entity) {
166 self.remove(entity);
167 }
168 self.insert(entity, value)
169 }
170
171 pub fn remove(&mut self, entity: XvcEntity) -> Option<T> {
175 if let Some(value) = self.map.remove(&entity) {
176 if let Some(vec_e) = self.entity_index.get_mut(&value) {
177 self.current.push_event(Event::Remove { entity });
179 vec_e.retain(|e| *e != entity);
180 return Some(value);
181 }
182 }
183 Option::<T>::None
184 }
185
186 fn build_map(previous: &EventLog<T>, current: &EventLog<T>) -> BTreeMap<XvcEntity, T> {
187 let mut map = BTreeMap::<XvcEntity, T>::new();
188
189 for event in previous.iter() {
190 match event {
191 Event::Add { entity, value } => map.insert(*entity, value.clone()),
192 Event::Remove { entity } => map.remove(entity),
193 };
194 }
195
196 for event in current.iter() {
197 match event {
198 Event::Add { entity, value } => map.insert(*entity, value.clone()),
199 Event::Remove { entity } => map.remove(entity),
200 };
201 }
202
203 map
204 }
205
206 fn build_index(map: &BTreeMap<XvcEntity, T>) -> BTreeMap<T, Vec<XvcEntity>> {
207 let mut entity_index = BTreeMap::<T, Vec<XvcEntity>>::new();
208
209 map.iter()
210 .for_each(|(entity, value)| match entity_index.get_mut(value) {
211 Some(v) => {
212 v.push(*entity);
213 }
214 None => {
215 entity_index.insert(value.clone(), vec![*entity]);
216 }
217 });
218
219 entity_index
220 }
221
222 pub fn from_dir(dir: &Path) -> Result<Self> {
224 let previous = EventLog::<T>::from_dir(dir)?;
225 let current = EventLog::<T>::new();
226 Ok(Self::from_event_logs(previous, current))
227 }
228
229 pub fn to_dir(&self, dir: &Path) -> Result<()> {
232 self.current.to_dir(dir)
233 }
234
235 pub fn len(&self) -> usize {
237 self.map.len()
238 }
239
240 pub fn is_empty(&self) -> bool {
242 self.map.is_empty()
243 }
244
245 pub fn subset<I>(&self, keys: I) -> Result<HStore<T>>
249 where
250 I: Iterator<Item = XvcEntity>,
251 {
252 let mut store = HStore::<T>::new();
253 for e in keys {
254 if let Some(v) = self.map.get(&e) {
255 store.map.insert(e, v.clone());
256 } else {
257 Error::CannotFindKeyInStore { key: e.to_string() }.warn();
258 }
259 }
260 Ok(store)
261 }
262
263 pub fn filter<F>(&self, predicate: F) -> HStore<T>
269 where
270 F: Fn(&XvcEntity, &T) -> bool,
271 {
272 let mut s = HashMap::new();
273 for (e, v) in self.map.iter() {
274 if predicate(e, v) {
275 s.insert(*e, v.clone());
276 }
277 }
278
279 HStore::from(s)
280 }
281
282 pub fn any<F>(&self, predicate: F) -> bool
286 where
287 F: Fn(&XvcEntity, &T) -> bool,
288 {
289 for (e, v) in self.map.iter() {
290 if predicate(e, v) {
291 return true;
292 }
293 }
294 false
295 }
296
297 pub fn first(&self) -> Option<(&XvcEntity, &T)> {
301 self.map.iter().next()
302 }
303
304 pub fn entities_for(&self, value: &T) -> Option<&Vec<XvcEntity>>
309 where
310 T: PartialEq,
311 {
312 self.entity_index.get(value)
313 }
314
315 pub fn entity_by_value(&self, value: &T) -> Option<XvcEntity> {
317 match self.entities_for(value) {
318 Some(vec_e) => vec_e.first().copied(),
319 None => None,
320 }
321 }
322
323 pub fn previous_events(&self) -> &EventLog<T> {
327 &self.previous
328 }
329
330 pub fn current_events(&self) -> &EventLog<T> {
334 &self.current
335 }
336
337 pub fn left_join<U>(&self, other: XvcStore<U>) -> XvcStore<(T, Option<U>)>
372 where
373 U: Storable,
374 {
375 let mut joined = XvcStore::<(T, Option<U>)>::new();
376 for (entity, value) in self.map.iter() {
377 joined.insert(*entity, (value.clone(), other.get(entity).cloned()));
378 }
379
380 joined
381 }
382
383 pub fn index_map(&self) -> Result<BTreeMap<T, XvcEntity>> {
390 let mut map = BTreeMap::new();
391
392 for (val, vec_e) in &self.entity_index {
393 map.insert(val.clone(), vec_e[0]);
394 }
395
396 Ok(map)
397 }
398
399 fn store_path(store_root: &Path) -> PathBuf {
400 store_root.join(format!("{}-store", <T as Storable>::type_description()))
401 }
402
403 pub fn load_store(store_root: &Path) -> Result<Self> {
405 let dir = Self::store_path(store_root);
406 Self::from_dir(&dir)
407 }
408
409 pub fn save_store(store: &XvcStore<T>, store_root: &Path) -> Result<()> {
411 let dir = Self::store_path(store_root);
412 store.to_dir(&dir)
413 }
414
415 pub fn save(&self, store_root: &Path) -> Result<()> {
418 Self::save_store(self, store_root)
419 }
420}
421
422#[cfg(test)]
423mod test {
424 use tempdir::TempDir;
425
426 use super::*;
427
428 #[test]
429 fn new() -> Result<()> {
430 let mut store = XvcStore::<String>::new();
431 store.insert((0, 123).into(), "0".into());
432 store.insert((1, 123).into(), "1".into());
433 assert_eq!(store.len(), 2);
434
435 assert_eq!(*store.get(&XvcEntity(0, 123)).unwrap(), String::from("0"));
436 assert_eq!(*store.get(&XvcEntity(1, 123)).unwrap(), String::from("1"));
437 Ok(())
438 }
439
440 #[test]
441 fn serde() -> Result<()> {
442 let td = TempDir::new("bstore-test")?;
443 let dir = td.path();
444
445 let mut store = XvcStore::<String>::new();
446
447 store.insert((0, 123).into(), "0".into());
448 store.insert((1, 123).into(), "1".into());
449 store.insert((2, 123).into(), "2".into());
450
451 store.to_dir(dir)?;
452
453 let reincarnation = XvcStore::<String>::from_dir(dir)?;
454
455 assert!(store.len() == reincarnation.len());
456 assert!(store.current_events().len() == reincarnation.previous_events().len());
457
458 assert!(reincarnation.current_events().is_empty());
459
460 let n_files_before = jwalk::WalkDir::new(dir).into_iter().count();
461 reincarnation.to_dir(dir)?;
462 let n_files_after = jwalk::WalkDir::new(dir).into_iter().count();
463
464 assert!(
465 n_files_before == n_files_after,
466 "before: {n_files_before} after: {n_files_after}"
467 );
468
469 Ok(())
470 }
471}