1use crate::model::file_like::FileLike;
2use crate::model::tree_like::{TreeLike, TreeLikeMut};
3use std::collections::HashSet;
4use uuid::Uuid;
5
6use super::errors::LbResult;
7
8pub trait StagedTreeLike: TreeLike {
9 type Base: TreeLike<F = Self::F>;
10 type Staged: TreeLike<F = Self::F>;
11
12 fn base(&self) -> &Self::Base;
13 fn staged(&self) -> &Self::Staged;
14}
15
16pub trait StagedTreeLikeMut<Base, Staged>:
19 StagedTreeLike<Base = Base, Staged = Staged> + TreeLikeMut
20where
21 Base: TreeLike<F = Self::F>,
22 Staged: TreeLikeMut<F = Self::F>,
23{
24 fn staged_mut(&mut self) -> &mut Self::Staged;
25
26 fn prune(&mut self) -> LbResult<()> {
27 let mut prunable = vec![];
28 for id in self.staged().ids() {
29 if let Some(staged) = self.staged().maybe_find(&id) {
30 if let Some(base) = self.base().maybe_find(&id) {
31 if staged == base {
32 prunable.push(id);
33 }
34 }
35 }
36 }
37
38 for id in prunable {
39 self.staged_mut().remove(id)?;
40 }
41 Ok(())
42 }
43
44 fn pruned(mut self) -> LbResult<Self> {
45 self.prune()?;
46 Ok(self)
47 }
48}
49
50#[derive(Clone, Debug)]
51pub struct StagedTree<Base, Staged>
52where
53 Base: TreeLike,
54 Staged: TreeLike<F = Base::F>,
55{
56 pub base: Base,
57 pub staged: Staged,
58 pub new: HashSet<Uuid>,
59 pub removed: HashSet<Uuid>,
60}
61
62impl<Base, Staged> StagedTree<Base, Staged>
63where
64 Base: TreeLike,
65 Staged: TreeLike<F = Base::F>,
66{
67 pub fn new(base: Base, staged: Staged) -> Self {
68 let mut new = HashSet::new();
69 for id in staged.ids() {
70 if base.maybe_find(&id).is_none() {
71 new.insert(id);
72 }
73 }
74 Self { base, staged, removed: HashSet::new(), new }
75 }
76}
77
78impl<Base> StagedTree<Base, Option<Base::F>>
79where
80 Base: TreeLike,
81{
82 pub fn removal(base: Base, removed: HashSet<Uuid>) -> Self {
84 Self { base, staged: None, removed, new: Default::default() }
85 }
86}
87
88impl<T> StagedTreeLike for &T
89where
90 T: StagedTreeLike,
91{
92 type Base = T::Base;
93 type Staged = T::Staged;
94
95 fn base(&self) -> &Self::Base {
96 T::base(self)
97 }
98 fn staged(&self) -> &Self::Staged {
99 T::staged(self)
100 }
101}
102
103impl<T> StagedTreeLike for &mut T
104where
105 T: StagedTreeLike,
106{
107 type Base = T::Base;
108 type Staged = T::Staged;
109
110 fn base(&self) -> &Self::Base {
111 T::base(self)
112 }
113 fn staged(&self) -> &Self::Staged {
114 T::staged(self)
115 }
116}
117
118impl<Base, Staged, T> StagedTreeLikeMut<Base, Staged> for &mut T
119where
120 Base: TreeLike<F = T::F>,
121 Staged: TreeLikeMut<F = T::F>,
122 T: StagedTreeLikeMut<Base, Staged>,
123{
124 fn staged_mut(&mut self) -> &mut Self::Staged {
125 T::staged_mut(self)
126 }
127}
128
129impl<Base, Staged> TreeLike for StagedTree<Base, Staged>
130where
131 Base: TreeLike,
132 Staged: TreeLike<F = Base::F>,
133{
134 type F = Base::F;
135
136 fn ids(&self) -> Vec<Uuid> {
137 let mut all_ids = self.base.ids();
138 all_ids.extend(&self.new);
139 all_ids.retain(|id| !self.removed.contains(id));
140
141 all_ids
142 }
143
144 fn maybe_find(&self, id: &Uuid) -> Option<&Self::F> {
145 if self.removed.contains(id) {
146 None
147 } else {
148 self.staged()
149 .maybe_find(id)
150 .or_else(|| self.base().maybe_find(id))
151 }
152 }
153}
154
155impl<Base, Staged> TreeLikeMut for StagedTree<Base, Staged>
156where
157 Base: TreeLike,
158 Staged: TreeLikeMut<F = Base::F>,
159{
160 fn insert(&mut self, f: Self::F) -> LbResult<Option<Self::F>> {
161 self.removed.remove(f.id());
163
164 if let Some(base) = self.base.maybe_find(f.id()) {
165 if *base == f {
166 return self.staged.remove(*f.id());
167 }
168 } else {
169 self.new.insert(*f.id());
170 }
171
172 self.staged.insert(f)
173 }
174
175 fn remove(&mut self, id: Uuid) -> LbResult<Option<Self::F>> {
176 self.removed.insert(id);
177 if let Some(staged) = self.staged.remove(id)? {
178 Ok(Some(staged))
179 } else {
180 Ok(self.base.maybe_find(&id).cloned())
181 }
182 }
183
184 fn clear(&mut self) -> LbResult<()> {
185 self.removed.extend(self.ids());
186 Ok(())
187 }
188}
189
190impl<Base, Staged> StagedTreeLike for StagedTree<Base, Staged>
191where
192 Base: TreeLike,
193 Staged: TreeLike<F = Base::F>,
194{
195 type Base = Base;
196 type Staged = Staged;
197
198 fn base(&self) -> &Self::Base {
199 &self.base
200 }
201
202 fn staged(&self) -> &Self::Staged {
203 &self.staged
204 }
205}
206
207impl<Base, Staged> StagedTreeLikeMut<Base, Staged> for StagedTree<Base, Staged>
208where
209 Base: TreeLike,
210 Staged: TreeLikeMut<F = Base::F>,
211{
212 fn staged_mut(&mut self) -> &mut Self::Staged {
213 &mut self.staged
214 }
215}