lockbook_shared/
staged.rs1use crate::file_like::FileLike;
2use crate::tree_like::{TreeLike, TreeLikeMut};
3use crate::SharedResult;
4use std::collections::HashSet;
5use uuid::Uuid;
6
7pub trait StagedTreeLike: TreeLike {
8 type Base: TreeLike<F = Self::F>;
9 type Staged: TreeLike<F = Self::F>;
10
11 fn base(&self) -> &Self::Base;
12 fn staged(&self) -> &Self::Staged;
13}
14
15pub trait StagedTreeLikeMut<Base, Staged>:
18 StagedTreeLike<Base = Base, Staged = Staged> + TreeLikeMut
19where
20 Base: TreeLike<F = Self::F>,
21 Staged: TreeLikeMut<F = Self::F>,
22{
23 fn staged_mut(&mut self) -> &mut Self::Staged;
24
25 fn prune(&mut self) -> SharedResult<()> {
26 let mut prunable = vec![];
27 for id in self.staged().ids() {
28 if let Some(staged) = self.staged().maybe_find(id) {
29 if let Some(base) = self.base().maybe_find(id) {
30 if staged == base {
31 prunable.push(*id);
32 }
33 }
34 }
35 }
36
37 for id in prunable {
38 self.staged_mut().remove(id)?;
39 }
40 Ok(())
41 }
42
43 fn pruned(mut self) -> SharedResult<Self> {
44 self.prune()?;
45 Ok(self)
46 }
47}
48
49#[derive(Debug)]
50pub struct StagedTree<Base, Staged>
51where
52 Base: TreeLike,
53 Staged: TreeLike<F = Base::F>,
54{
55 pub base: Base,
56 pub staged: Staged,
57 pub removed: HashSet<Uuid>,
58}
59
60impl<Base, Staged> StagedTree<Base, Staged>
61where
62 Base: TreeLike,
63 Staged: TreeLike<F = Base::F>,
64{
65 pub fn new(base: Base, staged: Staged) -> Self {
66 Self { base, staged, removed: HashSet::new() }
67 }
68}
69
70impl<Base> StagedTree<Base, Option<Base::F>>
71where
72 Base: TreeLike,
73{
74 pub fn removal(base: Base, removed: HashSet<Uuid>) -> Self {
75 Self { base, staged: None, removed }
76 }
77}
78
79impl<Base, Staged> TreeLike for StagedTree<Base, Staged>
80where
81 Base: TreeLike,
82 Staged: TreeLike<F = Base::F>,
83{
84 type F = Base::F;
85
86 fn ids(&self) -> HashSet<&Uuid> {
87 self.base()
88 .ids()
89 .into_iter()
90 .chain(self.staged().ids())
91 .filter(|id| !self.removed.contains(id))
92 .collect()
93 }
94
95 fn maybe_find(&self, id: &Uuid) -> Option<&Self::F> {
96 if self.removed.contains(id) {
97 None
98 } else {
99 self.staged()
100 .maybe_find(id)
101 .or_else(|| self.base().maybe_find(id))
102 }
103 }
104}
105
106impl<Base, Staged> TreeLikeMut for StagedTree<Base, Staged>
107where
108 Base: TreeLike,
109 Staged: TreeLikeMut<F = Base::F>,
110{
111 fn insert(&mut self, f: Self::F) -> SharedResult<Option<Self::F>> {
112 self.removed.remove(f.id());
113 if let Some(base) = self.base.maybe_find(f.id()) {
114 if *base == f {
115 return self.staged.remove(*f.id());
116 }
117 }
118
119 self.staged.insert(f)
120 }
121
122 fn remove(&mut self, id: Uuid) -> SharedResult<Option<Self::F>> {
123 self.removed.insert(id);
124 if let Some(staged) = self.staged.remove(id)? {
125 Ok(Some(staged))
126 } else {
127 Ok(self.base.maybe_find(&id).cloned())
128 }
129 }
130
131 fn clear(&mut self) -> SharedResult<()> {
132 self.removed.extend(self.owned_ids());
133 Ok(())
134 }
135}
136
137impl<Base, Staged> StagedTreeLike for StagedTree<Base, Staged>
138where
139 Base: TreeLike,
140 Staged: TreeLike<F = Base::F>,
141{
142 type Base = Base;
143 type Staged = Staged;
144
145 fn base(&self) -> &Self::Base {
146 &self.base
147 }
148
149 fn staged(&self) -> &Self::Staged {
150 &self.staged
151 }
152}
153
154impl<Base, Staged> StagedTreeLikeMut<Base, Staged> for StagedTree<Base, Staged>
155where
156 Base: TreeLike,
157 Staged: TreeLikeMut<F = Base::F>,
158{
159 fn staged_mut(&mut self) -> &mut Self::Staged {
160 &mut self.staged
161 }
162}