lb_rs/model/
tree_like.rs

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    // todo: iterator using const generics
14    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}