Skip to main content

vfs/engine/mem/
object_backend.rs

1use crate::engine::block::ObjectBackend;
2use crate::engine::error::{VfsError, VfsResult};
3use crate::engine::types::{ObjectEntry, ObjectMeta};
4use async_trait::async_trait;
5use std::collections::{BTreeMap, BTreeSet};
6use std::sync::{Arc, Mutex};
7
8#[derive(Debug, Clone)]
9struct StoredObject {
10    data: Vec<u8>,
11    meta: ObjectMeta,
12}
13
14#[derive(Debug, Clone, Default)]
15pub struct MemoryObjectBackend {
16    objects: Arc<Mutex<BTreeMap<String, StoredObject>>>,
17}
18
19impl MemoryObjectBackend {
20    pub fn new() -> Self {
21        Self::default()
22    }
23}
24
25#[async_trait]
26impl ObjectBackend for MemoryObjectBackend {
27    async fn list(&self, prefix: &str) -> VfsResult<Vec<ObjectEntry>> {
28        let objects = self.objects.lock().expect("object mutex poisoned");
29        let mut entries = Vec::new();
30        let mut prefixes = BTreeSet::new();
31        for (key, object) in objects.range(prefix.to_string()..) {
32            if !key.starts_with(prefix) {
33                break;
34            }
35            let rest = &key[prefix.len()..];
36            if rest.is_empty() {
37                entries.push(ObjectEntry {
38                    name: key.clone(),
39                    size: object.meta.size,
40                    mtime: object.meta.mtime,
41                    is_prefix: false,
42                });
43                continue;
44            }
45            if let Some((head, _)) = rest.split_once('/') {
46                prefixes.insert(format!("{prefix}{head}/"));
47            } else {
48                entries.push(ObjectEntry {
49                    name: key.clone(),
50                    size: object.meta.size,
51                    mtime: object.meta.mtime,
52                    is_prefix: false,
53                });
54            }
55        }
56        entries.extend(prefixes.into_iter().map(|name| ObjectEntry {
57            name,
58            size: 0,
59            mtime: crate::engine::types::Timespec::now(),
60            is_prefix: true,
61        }));
62        Ok(entries)
63    }
64
65    async fn head(&self, key: &str) -> VfsResult<Option<ObjectMeta>> {
66        Ok(self
67            .objects
68            .lock()
69            .expect("object mutex poisoned")
70            .get(key)
71            .map(|object| object.meta.clone()))
72    }
73
74    async fn get_range(&self, key: &str, off: u64, len: u64) -> VfsResult<Vec<u8>> {
75        let objects = self.objects.lock().expect("object mutex poisoned");
76        let object = objects.get(key).ok_or_else(|| VfsError::enoent(key))?;
77        let start = usize::try_from(off)
78            .map_err(|_| VfsError::einval(format!("range offset is too large: {off}")))?;
79        let len = usize::try_from(len)
80            .map_err(|_| VfsError::einval(format!("range length is too large: {len}")))?;
81        if start >= object.data.len() {
82            return Ok(Vec::new());
83        }
84        let end = start.saturating_add(len).min(object.data.len());
85        Ok(object.data[start..end].to_vec())
86    }
87
88    async fn put(&self, key: &str, data: &[u8], mut meta: ObjectMeta) -> VfsResult<()> {
89        meta.size = data.len() as u64;
90        self.objects.lock().expect("object mutex poisoned").insert(
91            key.to_string(),
92            StoredObject {
93                data: data.to_vec(),
94                meta,
95            },
96        );
97        Ok(())
98    }
99
100    async fn copy(&self, src: &str, dst: &str) -> VfsResult<()> {
101        let mut objects = self.objects.lock().expect("object mutex poisoned");
102        let object = objects
103            .get(src)
104            .cloned()
105            .ok_or_else(|| VfsError::enoent(src))?;
106        objects.insert(dst.to_string(), object);
107        Ok(())
108    }
109
110    async fn delete(&self, key: &str) -> VfsResult<()> {
111        self.objects
112            .lock()
113            .expect("object mutex poisoned")
114            .remove(key);
115        Ok(())
116    }
117}