blobary/
store.rs

1// This is free and unencumbered software released into the public domain.
2
3use crate::{Blob, BlobHash, BlobID, BlobStoreError, IndexedBlobStoreIterator};
4use std::{io::Read, path::Path};
5
6pub type Result<T> = std::result::Result<T, BlobStoreError>;
7
8pub trait BlobStore {
9    /// Returns the number of blobs in this store.
10    fn count(&self) -> Result<usize>;
11
12    /// Determines if the store contains a blob with the given BLAKE3 hash.
13    fn contains_hash(&self, blob_hash: BlobHash) -> Result<bool>;
14
15    /// Fetches a blob by its BLAKE3 hash.
16    fn get_by_hash(&self, blob_hash: BlobHash) -> Result<Option<Blob>>;
17
18    /// Stores a blob and returns its metadata.
19    fn put(&mut self, blob_data: &mut dyn Read) -> Result<(bool, Blob)>;
20
21    /// Removes a blob by its BLAKE3 hash.
22    fn remove(&mut self, blob_hash: BlobHash) -> Result<bool>;
23}
24
25pub trait IndexedBlobStore: BlobStore {
26    /// Converts a BLAKE3 hash to a store ID.
27    fn hash_to_id(&self, blob_hash: BlobHash) -> Result<Option<BlobID>>;
28
29    /// Converts a store ID to a BLAKE3 hash.
30    fn id_to_hash(&self, blob_id: BlobID) -> Result<Option<BlobHash>>;
31
32    /// Fetches a blob by its store ID.
33    fn get_by_id(&self, blob_id: BlobID) -> Result<Option<Blob>>;
34}
35
36pub trait BlobStoreExt: BlobStore {
37    /// Determines if the store contains no blobs.
38    fn is_empty(&self) -> Result<bool> {
39        Ok(self.count()? == 0)
40    }
41
42    /// Stores a blob and returns its store ID.
43    fn put_bytes(&mut self, data: impl AsRef<[u8]>) -> Result<(bool, Blob)> {
44        self.put(&mut data.as_ref())
45    }
46
47    /// Stores a blob and returns its store ID.
48    fn put_string(&mut self, data: impl AsRef<str>) -> Result<(bool, Blob)> {
49        self.put(&mut data.as_ref().as_bytes())
50    }
51
52    /// Stores a blob and returns its store ID.
53    fn put_file(&mut self, path: impl AsRef<Path>) -> Result<(bool, Blob)> {
54        self.put(&mut std::fs::File::open(path)?)
55    }
56}
57
58#[derive(Copy, Clone, Debug)]
59pub struct BlobStoreOptions {
60    pub writable: bool,
61}
62
63impl Default for BlobStoreOptions {
64    fn default() -> Self {
65        Self { writable: true }
66    }
67}
68
69impl BlobStoreExt for dyn BlobStore {}
70
71impl BlobStoreExt for dyn IndexedBlobStore {}
72
73impl<'a> IntoIterator for &'a mut dyn IndexedBlobStore {
74    type Item = Blob;
75    type IntoIter = IndexedBlobStoreIterator<'a>;
76
77    fn into_iter(self) -> Self::IntoIter {
78        IndexedBlobStoreIterator::new(self)
79    }
80}