1use 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 fn count(&self) -> Result<usize>;
11
12 fn contains_hash(&self, blob_hash: BlobHash) -> Result<bool>;
14
15 fn get_by_hash(&self, blob_hash: BlobHash) -> Result<Option<Blob>>;
17
18 fn put(&mut self, blob_data: &mut dyn Read) -> Result<(bool, Blob)>;
20
21 fn remove(&mut self, blob_hash: BlobHash) -> Result<bool>;
23}
24
25pub trait IndexedBlobStore: BlobStore {
26 fn hash_to_id(&self, blob_hash: BlobHash) -> Result<Option<BlobID>>;
28
29 fn id_to_hash(&self, blob_id: BlobID) -> Result<Option<BlobHash>>;
31
32 fn get_by_id(&self, blob_id: BlobID) -> Result<Option<Blob>>;
34}
35
36pub trait BlobStoreExt: BlobStore {
37 fn is_empty(&self) -> Result<bool> {
39 Ok(self.count()? == 0)
40 }
41
42 fn put_bytes(&mut self, data: impl AsRef<[u8]>) -> Result<(bool, Blob)> {
44 self.put(&mut data.as_ref())
45 }
46
47 fn put_string(&mut self, data: impl AsRef<str>) -> Result<(bool, Blob)> {
49 self.put(&mut data.as_ref().as_bytes())
50 }
51
52 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}