structfs_ll_store/
traits.rs1use bytes::Bytes;
4
5use crate::LLError;
6
7#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
25pub struct LLPath(Vec<Bytes>);
26
27impl LLPath {
28 pub fn new() -> Self {
30 LLPath(Vec::new())
31 }
32
33 pub fn from_components(components: Vec<Bytes>) -> Self {
35 LLPath(components)
36 }
37
38 pub fn components(&self) -> &[Bytes] {
40 &self.0
41 }
42
43 pub fn into_components(self) -> Vec<Bytes> {
45 self.0
46 }
47
48 pub fn push(&mut self, component: Bytes) {
50 self.0.push(component);
51 }
52
53 pub fn as_byte_refs(&self) -> Vec<&[u8]> {
56 self.0.iter().map(|c| c.as_ref()).collect()
57 }
58}
59
60impl std::ops::Deref for LLPath {
61 type Target = [Bytes];
62 fn deref(&self) -> &[Bytes] {
63 &self.0
64 }
65}
66
67impl FromIterator<Bytes> for LLPath {
68 fn from_iter<I: IntoIterator<Item = Bytes>>(iter: I) -> Self {
69 LLPath(iter.into_iter().collect())
70 }
71}
72
73impl IntoIterator for LLPath {
74 type Item = Bytes;
75 type IntoIter = std::vec::IntoIter<Bytes>;
76 fn into_iter(self) -> Self::IntoIter {
77 self.0.into_iter()
78 }
79}
80
81impl<'a> IntoIterator for &'a LLPath {
82 type Item = &'a Bytes;
83 type IntoIter = std::slice::Iter<'a, Bytes>;
84 fn into_iter(self) -> Self::IntoIter {
85 self.0.iter()
86 }
87}
88
89impl From<Vec<Bytes>> for LLPath {
90 fn from(components: Vec<Bytes>) -> Self {
91 LLPath(components)
92 }
93}
94
95pub trait LLReader: Send + Sync {
104 fn ll_read(&mut self, path: &[&[u8]]) -> Result<Option<Bytes>, LLError>;
128}
129
130pub trait LLWriter: Send + Sync {
139 fn ll_write(&mut self, path: &[&[u8]], data: Bytes) -> Result<LLPath, LLError>;
163}
164
165pub trait LLStore: LLReader + LLWriter {}
171impl<T: LLReader + LLWriter> LLStore for T {}
172
173impl<T: LLReader + ?Sized> LLReader for &mut T {
176 fn ll_read(&mut self, path: &[&[u8]]) -> Result<Option<Bytes>, LLError> {
177 (*self).ll_read(path)
178 }
179}
180
181impl<T: LLWriter + ?Sized> LLWriter for &mut T {
182 fn ll_write(&mut self, path: &[&[u8]], data: Bytes) -> Result<LLPath, LLError> {
183 (*self).ll_write(path, data)
184 }
185}
186
187impl<T: LLReader + ?Sized> LLReader for Box<T> {
188 fn ll_read(&mut self, path: &[&[u8]]) -> Result<Option<Bytes>, LLError> {
189 self.as_mut().ll_read(path)
190 }
191}
192
193impl<T: LLWriter + ?Sized> LLWriter for Box<T> {
194 fn ll_write(&mut self, path: &[&[u8]], data: Bytes) -> Result<LLPath, LLError> {
195 self.as_mut().ll_write(path, data)
196 }
197}
198
199#[cfg(test)]
200mod tests {
201 use super::*;
202 use std::collections::HashMap;
203
204 struct TestLLStore {
206 data: HashMap<Vec<Vec<u8>>, Bytes>,
207 }
208
209 impl TestLLStore {
210 fn new() -> Self {
211 Self {
212 data: HashMap::new(),
213 }
214 }
215 }
216
217 impl LLReader for TestLLStore {
218 fn ll_read(&mut self, path: &[&[u8]]) -> Result<Option<Bytes>, LLError> {
219 let key: Vec<Vec<u8>> = path.iter().map(|c| c.to_vec()).collect();
220 Ok(self.data.get(&key).cloned())
221 }
222 }
223
224 impl LLWriter for TestLLStore {
225 fn ll_write(&mut self, path: &[&[u8]], data: Bytes) -> Result<LLPath, LLError> {
226 let key: Vec<Vec<u8>> = path.iter().map(|c| c.to_vec()).collect();
227 self.data.insert(key, data);
228 Ok(path.iter().map(|c| Bytes::copy_from_slice(c)).collect())
229 }
230 }
231
232 #[test]
233 fn basic_read_write_works() {
234 let mut store = TestLLStore::new();
235
236 let path = &[b"users".as_slice(), b"123".as_slice()];
238 let data = Bytes::from_static(b"hello world");
239 store.ll_write(path, data.clone()).unwrap();
240
241 let result = store.ll_read(path).unwrap();
243 assert_eq!(result, Some(data));
244
245 let result = store.ll_read(&[b"nonexistent"]).unwrap();
247 assert_eq!(result, None);
248 }
249
250 #[test]
251 fn object_safety_works() {
252 let mut store = TestLLStore::new();
253 let boxed: &mut dyn LLStore = &mut store;
254
255 boxed
256 .ll_write(&[b"test"], Bytes::from_static(b"data"))
257 .unwrap();
258 let result = boxed.ll_read(&[b"test"]).unwrap();
259 assert_eq!(result, Some(Bytes::from_static(b"data")));
260 }
261
262 #[test]
263 fn mut_ref_blanket_impl_works() {
264 let mut store = TestLLStore::new();
265 let store_ref: &mut TestLLStore = &mut store;
266
267 store_ref
268 .ll_write(&[b"ref_test"], Bytes::from_static(b"ref_data"))
269 .unwrap();
270 let result = store_ref.ll_read(&[b"ref_test"]).unwrap();
271 assert_eq!(result, Some(Bytes::from_static(b"ref_data")));
272 }
273
274 #[test]
275 fn box_blanket_impl_works() {
276 let store = TestLLStore::new();
277 let mut boxed: Box<TestLLStore> = Box::new(store);
278
279 boxed
280 .ll_write(&[b"box_test"], Bytes::from_static(b"box_data"))
281 .unwrap();
282 let result = boxed.ll_read(&[b"box_test"]).unwrap();
283 assert_eq!(result, Some(Bytes::from_static(b"box_data")));
284 }
285
286 #[test]
287 fn box_dyn_works() {
288 let store = TestLLStore::new();
289 let mut boxed: Box<dyn LLStore> = Box::new(store);
290
291 boxed
292 .ll_write(&[b"dyn_test"], Bytes::from_static(b"dyn_data"))
293 .unwrap();
294 let result = boxed.ll_read(&[b"dyn_test"]).unwrap();
295 assert_eq!(result, Some(Bytes::from_static(b"dyn_data")));
296 }
297}