1use crate::JournalError;
2use crate::Tag;
3use std::collections::HashMap;
4use std::collections::HashSet;
5use std::fmt::Debug;
6use std::hash::Hash;
7use std::ops::Range;
8
9#[cfg(feature = "serde")]
10use serde::Deserialize;
11#[cfg(feature = "serde")]
12use serde::Serialize;
13#[cfg(feature = "serde")]
14use serde::de::Deserialize as DeserializeTrait;
15#[cfg(feature = "serde")]
16use serde::de::Deserializer;
17#[cfg(feature = "serde")]
18use serde::ser::Serialize as SerializeTrait;
19#[cfg(feature = "serde")]
20use serde::ser::Serializer;
21
22#[derive(Clone, Copy)]
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24struct Insert<K, V> {
25 pub key: K,
26 pub val: V,
27 pub replacing: Option<V>,
28}
29
30impl<K: Eq + Hash + Clone, V: Clone> Insert<K, V> {
31 pub fn forward(&self, map: &mut HashMap<K, V>) {
32 map.insert(self.key.clone(), self.val.clone());
33 }
34
35 pub fn reverse(&self, map: &mut HashMap<K, V>) {
36 match self.replacing.clone() {
37 Some(val) => {
38 map.insert(self.key.clone(), val);
39 }
40 None => {
41 map.remove(&self.key);
42 }
43 }
44 }
45}
46
47impl<K: Debug, V: Debug> std::fmt::Debug for Insert<K, V> {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 match &self.replacing {
50 Some(replacing) => write!(f, "[>] {:?}:{:?}->{:?}", self.key, replacing, self.val),
51 None => write!(f, "[+] {:?}:{:?}", self.key, self.val),
52 }
53 }
54}
55
56#[derive(Clone, Copy)]
57#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
58struct Remove<K, V> {
59 pub key: K,
60 pub val: V,
61}
62
63impl<K: Eq + Hash + Clone, V: Clone> Remove<K, V> {
64 pub fn forward(&self, map: &mut HashMap<K, V>) {
65 map.remove(&self.key);
66 }
67
68 pub fn reverse(&self, map: &mut HashMap<K, V>) {
69 map.insert(self.key.clone(), self.val.clone());
70 }
71}
72
73impl<K: Debug, V: Debug> std::fmt::Debug for Remove<K, V> {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 write!(f, "[-] '{:?}':'{:?}'", self.key, self.val)
76 }
77}
78
79#[derive(Clone, Copy)]
80#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
81enum JournalEntry<K, V, T> {
82 Insert(Insert<K, V>),
83 Remove(Remove<K, V>),
84 Tag(Tag<T>),
85}
86
87impl<K: Clone + Hash + Eq, V: Clone, T: Hash + Eq + Clone> JournalEntry<K, V, T> {
88 pub fn reverse(&self, map: &mut HashMap<K, V>) {
89 match self {
90 Self::Insert(entry_data) => entry_data.reverse(map),
91 Self::Remove(entry_data) => entry_data.reverse(map),
92 Self::Tag(_) => {}
93 }
94 }
95
96 pub fn forward(&self, map: &mut HashMap<K, V>) {
97 match self {
98 Self::Insert(entry_data) => entry_data.forward(map),
99 Self::Remove(entry_data) => entry_data.forward(map),
100 Self::Tag(_) => {}
101 }
102 }
103}
104
105impl<K: Debug + Hash + Eq, V: Debug, T: Debug + Hash + Eq> std::fmt::Debug
106 for JournalEntry<K, V, T>
107{
108 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
109 match self {
110 JournalEntry::Insert(entry) => {
111 write!(f, "{:?}", entry)
112 }
113 JournalEntry::Remove(entry) => {
114 write!(f, "{:?}", entry)
115 }
116 JournalEntry::Tag(entry) => {
117 write!(f, "{:?}", entry)
118 }
119 }
120 }
121}
122
123pub struct JournalMap<K: Eq + Hash, V, T: Eq + Hash> {
194 journal: Vec<JournalEntry<K, V, T>>,
195 tags: HashSet<T>,
199 map: HashMap<K, V>,
200 current_tag_index: Option<usize>,
201}
202
203impl<K: Hash + Eq, V, T: Hash + Eq> Default for JournalMap<K, V, T> {
204 fn default() -> Self {
205 Self::new()
206 }
207}
208
209impl<K: Hash + Eq, V, T: Hash + Eq> JournalMap<K, V, T> {
210 pub fn new() -> Self {
211 Self {
212 journal: Vec::new(),
213 tags: HashSet::new(),
214 map: HashMap::new(),
215 current_tag_index: None,
216 }
217 }
218
219 pub fn with_capacity(capacity: usize) -> Self {
220 Self {
221 journal: Vec::with_capacity(capacity),
222 tags: HashSet::with_capacity(capacity),
223 map: HashMap::with_capacity(capacity),
224 current_tag_index: None,
225 }
226 }
227
228 #[inline]
229 pub fn len(&self) -> usize {
230 self.map.len()
231 }
232
233 #[inline]
234 pub fn journal_len(&self) -> usize {
235 self.journal.len()
236 }
237
238 #[inline]
239 pub fn is_empty(&self) -> bool {
240 self.map.is_empty()
241 }
242
243 pub fn current_tag(&self) -> Option<&T> {
244 let Some(i_tag) = self.current_tag_index else {
245 return None;
246 };
247
248 let JournalEntry::Tag(tag) = &self.journal[i_tag] else {
249 panic!("Tag not at tag index");
250 };
251
252 Some(&tag.tag)
253 }
254
255 #[inline]
256 pub fn as_hashmap(&self) -> &HashMap<K, V> {
257 &self.map
258 }
259
260 pub fn clear_all(&mut self) {
262 self.map.clear();
263 self.journal.clear();
264 self.tags.clear();
265 self.current_tag_index = None;
266 }
267
268 fn transaction_prep(&mut self) {
271 let Some(i_tag) = self.current_tag_index.take() else {
272 return;
273 };
274
275 let i_trunc = i_tag + 1;
276
277 for entry in self.journal[i_trunc..].iter() {
278 if let JournalEntry::Tag(tag) = entry {
279 self.tags.remove(&tag.tag);
280 }
281 }
282
283 self.journal.truncate(i_trunc);
284 }
285
286 fn i_tag_reverse_seek<MatchFn: Fn(&T) -> bool>(
291 &mut self,
292 match_fn: MatchFn,
293 ) -> Option<Range<usize>> {
294 let i_reverse_end = self.current_tag_index.unwrap_or(self.journal.len());
295
296 let Some(i_tag_rev_rel) = self.journal[..i_reverse_end]
297 .iter()
298 .rev()
299 .position(|entry| {
300 if let JournalEntry::Tag(tag) = entry
301 && match_fn(&tag.tag)
302 {
303 true
304 } else {
305 false
306 }
307 })
308 else {
309 return None;
310 };
311
312 let i_tag = i_reverse_end - i_tag_rev_rel - 1;
313
314 self.current_tag_index = Some(i_tag);
315
316 let i_reverse_start = i_tag + 1;
317
318 Some(i_reverse_start..i_reverse_end)
319 }
320
321 fn i_tag_forward_seek<MatchFn: Fn(&T) -> bool>(
326 &mut self,
327 match_fn: MatchFn,
328 ) -> Option<Range<usize>> {
329 let Some(i_current_tag) = self.current_tag_index else {
330 return None;
331 };
332
333 let i_forward_start = i_current_tag + 1;
334
335 let Some(i_next_tag_rel) = self.journal[i_forward_start..].iter().position(|entry| {
336 if let JournalEntry::Tag(tag) = entry
337 && match_fn(&tag.tag)
338 {
339 true
340 } else {
341 false
342 }
343 }) else {
344 return None;
345 };
346
347 let i_next_tag = i_forward_start + i_next_tag_rel;
348
349 self.current_tag_index = Some(i_next_tag);
350
351 let i_forward_end = i_next_tag;
352
353 Some(i_forward_start..i_forward_end)
354 }
355
356 pub fn retain_tags<RetainFn: Fn(&T) -> bool>(&mut self, retain_fn: RetainFn) {
358 self.current_tag_index = None;
359
360 self.journal.retain(|entry| {
361 let JournalEntry::Tag(tag) = entry else {
362 return true;
363 };
364
365 let retain = retain_fn(&tag.tag);
366
367 if !retain {
368 self.tags.remove(&tag.tag);
369 }
370
371 retain
372 });
373 }
374}
375
376impl<K: Eq + Hash + Clone, V: Clone, T: Hash + Eq + Clone> JournalMap<K, V, T> {
377 pub fn from_iter<Iter: Iterator<Item = (K, V)>>(iter: Iter, init_tag: Option<T>) -> Self {
380 let map: HashMap<K, V> = HashMap::from_iter(iter);
381
382 let capacity = map.capacity() + init_tag.is_some() as usize;
383
384 let mut journal_map = Self {
385 journal: Vec::with_capacity(capacity),
386 tags: HashSet::with_capacity((capacity / 2).min(4)),
387 map,
388 current_tag_index: None,
389 };
390
391 if let Some(tag) = init_tag {
392 journal_map.tags.insert(tag.clone());
393
394 journal_map.journal.push(JournalEntry::Tag(Tag { tag }));
395 }
396
397 for (key, val) in journal_map.map.iter() {
398 journal_map.journal.push(JournalEntry::Insert(Insert {
399 key: key.clone(),
400 val: val.clone(),
401 replacing: None,
402 }));
403 }
404
405 journal_map
406 }
407
408 pub fn insert(&mut self, key: K, val: V) -> Option<V> {
412 self.transaction_prep();
413
414 let replacing = self.map.insert(key.clone(), val.clone());
415
416 let entry = JournalEntry::Insert(Insert {
417 key,
418 val,
419 replacing: replacing.clone(),
420 });
421
422 self.journal.push(entry);
423
424 replacing
425 }
426
427 pub fn get(&self, key: &K) -> Option<&V> {
428 self.map.get(key)
429 }
430
431 pub fn contains_key(&self, key: &K) -> bool {
432 self.map.contains_key(key)
433 }
434
435 pub fn remove(&mut self, key: K) -> Option<V> {
436 self.transaction_prep();
437
438 let value_opt = self.map.remove(&key);
439
440 if let Some(val) = value_opt.clone() {
441 self.journal.push(JournalEntry::Remove(Remove { key, val }));
442 }
443
444 value_opt
445 }
446
447 pub fn clear(&mut self) {
451 self.transaction_prep();
452
453 for (key, val) in self.map.iter() {
454 self.journal.push(JournalEntry::Remove(Remove {
455 key: key.clone(),
456 val: val.clone(),
457 }));
458 }
459
460 self.map.clear();
461 }
462
463 pub fn append_tag(&mut self, tag: T) -> Result<(), JournalError<T>> {
466 if self.tags.contains(&tag) {
467 return Err(JournalError::TagExists { tag });
468 }
469 self.current_tag_index = Some(self.journal.len());
470 self.journal
471 .push(JournalEntry::Tag(Tag { tag: tag.clone() }));
472 self.tags.insert(tag);
473
474 Ok(())
475 }
476
477 pub fn reverse_to_next(&mut self) -> bool {
480 let Some(range) = self.i_tag_reverse_seek(|_| true) else {
481 return false;
482 };
483
484 if range.is_empty() {
485 return false;
486 }
487
488 self.reverse_range(range);
489
490 true
491 }
492
493 pub fn reverse_to_tag(&mut self, tag: &T) -> bool {
496 let Some(range) = self.i_tag_reverse_seek(|other_tag| other_tag == tag) else {
497 return false;
498 };
499
500 if range.is_empty() {
501 return false;
502 }
503
504 self.reverse_range(range);
505
506 true
507 }
508
509 pub fn forward_to_next(&mut self) -> bool {
512 let Some(range) = self.i_tag_forward_seek(|_| true) else {
513 return false;
514 };
515
516 if range.is_empty() {
517 return false;
518 }
519
520 self.forward_range(range);
521
522 true
523 }
524
525 pub fn forward_to_tag(&mut self, tag: &T) -> bool {
528 let Some(range) = self.i_tag_forward_seek(|other_tag| other_tag == tag) else {
529 return false;
530 };
531
532 if range.is_empty() {
533 return false;
534 }
535
536 self.forward_range(range);
537
538 true
539 }
540
541 fn reverse_range(&mut self, range: Range<usize>) {
543 for entry in self.journal[range].iter().rev() {
544 entry.reverse(&mut self.map);
545 }
546 }
547
548 fn forward_range(&mut self, range: Range<usize>) {
550 for entry in self.journal[range].iter() {
551 entry.forward(&mut self.map);
552 }
553 }
554
555 pub fn generate_journal(&self, truncate_future: bool) -> JournalMapJournal<K, V, T> {
561 let i_copy_start = 0;
562 let i_copy_end = if truncate_future && let Some(i_tag) = self.current_tag_index {
563 i_tag + 1
564 } else {
565 self.journal.len()
566 };
567
568 let journal_src = &self.journal[i_copy_start..i_copy_end];
569
570 let journal = journal_src.to_vec();
571
572 JournalMapJournal { journal }
573 }
574
575 pub fn from_journal(val: &JournalMapJournal<K, V, T>) -> Self {
578 let capacity = val.journal.len();
579 let map = HashMap::with_capacity(capacity);
580 let tags = HashSet::with_capacity(capacity);
581 let mut journal_map = Self {
582 map,
583 tags,
584 journal: val.journal.clone(),
585 current_tag_index: None,
586 };
587
588 for entry in journal_map.journal.iter() {
589 entry.forward(&mut journal_map.map);
590
591 if let JournalEntry::Tag(tag) = entry {
592 journal_map.tags.insert(tag.tag.clone());
593 }
594 }
595
596 journal_map
597 }
598}
599
600impl<K: Debug + Eq + Hash, V: Debug, T: Debug + Eq + Hash> std::fmt::Debug for JournalMap<K, V, T> {
601 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
602 let alternate = f.alternate();
603 write!(f, "{{")?;
604 for (i_entry, entry) in self.journal.iter().enumerate() {
605 if alternate {
606 write!(f, "\n\t")?;
607 }
608
609 if let Some(i_tag) = self.current_tag_index
610 && i_tag == i_entry
611 {
612 write!(f, "@ ")?;
613 }
614
615 write!(f, "{:?},", entry)?;
616 }
617
618 if alternate {
619 writeln!(f)?;
620 }
621
622 write!(f, "}}")?;
623
624 Ok(())
625 }
626}
627
628#[derive(Debug, Clone)]
632pub struct JournalMapJournal<K: Hash + Eq, V, T: Hash + Eq> {
633 journal: Vec<JournalEntry<K, V, T>>,
634}
635
636impl<K: Hash + Eq, V, T: Hash + Eq> JournalMapJournal<K, V, T> {
637 #[inline]
638 pub fn len(&self) -> usize {
639 self.journal.len()
640 }
641}
642
643#[cfg(feature = "serde")]
644impl<K: SerializeTrait + Hash + Eq, V: SerializeTrait, T: SerializeTrait + Eq + Hash> SerializeTrait
645 for JournalMapJournal<K, V, T>
646{
647 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
648 self.journal.serialize(serializer)
649 }
650}
651
652#[cfg(feature = "serde")]
653impl<
654 'de,
655 K: DeserializeTrait<'de> + Hash + Eq,
656 V: DeserializeTrait<'de>,
657 T: DeserializeTrait<'de> + Eq + Hash,
658> DeserializeTrait<'de> for JournalMapJournal<K, V, T>
659{
660 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
661 Ok(Self {
662 journal: Vec::deserialize(deserializer)?,
663 })
664 }
665}