1use crate::model::file_like::FileLike;
2use crate::model::lazy::LazyTree;
3use crate::model::staged::StagedTree;
4use std::collections::HashMap;
5use std::fmt::Debug;
6use uuid::Uuid;
7
8use super::errors::{LbErrKind, LbResult};
9
10pub trait TreeLike: Sized {
11 type F: FileLike + Debug;
12
13 fn ids(&self) -> Vec<Uuid>;
15 fn maybe_find(&self, id: &Uuid) -> Option<&Self::F>;
16
17 fn find(&self, id: &Uuid) -> LbResult<&Self::F> {
18 self.maybe_find(id)
19 .ok_or_else(|| LbErrKind::FileNonexistent.into())
20 }
21
22 fn maybe_find_parent<F2: FileLike>(&self, file: &F2) -> Option<&Self::F> {
23 self.maybe_find(file.parent())
24 }
25
26 fn find_parent<F2: FileLike>(&self, file: &F2) -> LbResult<&Self::F> {
27 self.maybe_find_parent(file)
28 .ok_or_else(|| LbErrKind::FileParentNonexistent.into())
29 }
30
31 fn all_files(&self) -> LbResult<Vec<&Self::F>> {
32 let ids = self.ids();
33 let mut all = Vec::with_capacity(ids.len());
34 for id in ids {
35 let meta = self.find(&id)?;
36 all.push(meta);
37 }
38
39 Ok(all)
40 }
41
42 fn stage<Staged>(&self, staged: Staged) -> StagedTree<&Self, Staged>
43 where
44 Staged: TreeLike<F = Self::F>,
45 Self: Sized,
46 {
47 StagedTree::new(self, staged)
48 }
49
50 fn to_staged<Staged>(self, staged: Staged) -> StagedTree<Self, Staged>
51 where
52 Staged: TreeLike<F = Self::F>,
53 Self: Sized,
54 {
55 StagedTree::new(self, staged)
56 }
57
58 fn as_lazy(&self) -> LazyTree<&Self> {
59 LazyTree::new(self)
60 }
61
62 fn to_lazy(self) -> LazyTree<Self> {
63 LazyTree::new(self)
64 }
65}
66
67pub trait TreeLikeMut: TreeLike {
68 fn insert(&mut self, f: Self::F) -> LbResult<Option<Self::F>>;
69 fn remove(&mut self, id: Uuid) -> LbResult<Option<Self::F>>;
70 fn clear(&mut self) -> LbResult<()>;
71}
72
73impl<T> TreeLike for &T
74where
75 T: TreeLike,
76{
77 type F = T::F;
78
79 fn ids(&self) -> Vec<Uuid> {
80 T::ids(self)
81 }
82
83 fn maybe_find(&self, id: &Uuid) -> Option<&Self::F> {
84 T::maybe_find(self, id)
85 }
86}
87
88impl<T> TreeLike for &mut T
89where
90 T: TreeLike,
91{
92 type F = T::F;
93
94 fn ids(&self) -> Vec<Uuid> {
95 T::ids(self)
96 }
97
98 fn maybe_find(&self, id: &Uuid) -> Option<&Self::F> {
99 T::maybe_find(self, id)
100 }
101}
102
103impl<T> TreeLikeMut for &mut T
104where
105 T: TreeLikeMut,
106{
107 fn insert(&mut self, f: Self::F) -> LbResult<Option<Self::F>> {
108 T::insert(self, f)
109 }
110
111 fn remove(&mut self, id: Uuid) -> LbResult<Option<Self::F>> {
112 T::remove(self, id)
113 }
114
115 fn clear(&mut self) -> LbResult<()> {
116 T::clear(self)
117 }
118}
119
120impl<F> TreeLike for Vec<F>
121where
122 F: FileLike,
123{
124 type F = F;
125
126 fn ids(&self) -> Vec<Uuid> {
127 self.iter().map(|f| *f.id()).collect()
128 }
129
130 fn maybe_find(&self, id: &Uuid) -> Option<&F> {
131 self.iter().find(|f| f.id() == id)
132 }
133}
134
135impl<F> TreeLikeMut for Vec<F>
136where
137 F: FileLike,
138{
139 fn insert(&mut self, f: F) -> LbResult<Option<F>> {
140 for (i, value) in self.iter().enumerate() {
141 if value.id() == f.id() {
142 let old = std::mem::replace(&mut self[i], f);
143 return Ok(Some(old));
144 }
145 }
146
147 self.push(f);
148
149 Ok(None)
150 }
151
152 fn remove(&mut self, id: Uuid) -> LbResult<Option<F>> {
153 for (i, value) in self.iter().enumerate() {
154 if *value.id() == id {
155 return Ok(Some(self.remove(i)));
156 }
157 }
158
159 Ok(None)
160 }
161
162 fn clear(&mut self) -> LbResult<()> {
163 self.clear();
164 Ok(())
165 }
166}
167
168impl<F> TreeLike for HashMap<Uuid, F>
169where
170 F: FileLike,
171{
172 type F = F;
173
174 fn ids(&self) -> Vec<Uuid> {
175 self.keys().copied().collect()
176 }
177
178 fn maybe_find(&self, id: &Uuid) -> Option<&F> {
179 self.get(id)
180 }
181}
182
183impl<F> TreeLikeMut for HashMap<Uuid, F>
184where
185 F: FileLike,
186{
187 fn insert(&mut self, f: F) -> LbResult<Option<F>> {
188 Ok(self.insert(*f.id(), f))
189 }
190
191 fn remove(&mut self, id: Uuid) -> LbResult<Option<F>> {
192 Ok(self.remove(&id))
193 }
194
195 fn clear(&mut self) -> LbResult<()> {
196 self.clear();
197 Ok(())
198 }
199}