mod memory;
#[cfg(feature = "filesystem")]
mod filesystem;
#[cfg(feature = "s3")]
mod s3;
pub use memory::MemoryBackend;
#[cfg(feature = "filesystem")]
pub use filesystem::FilesystemBackend;
#[cfg(feature = "s3")]
pub use self::s3::{S3Backend, S3Config};
use crate::protocol::BlobDescriptor;
pub trait BlobBackend: Send + Sync {
fn insert(&mut self, data: Vec<u8>, base_url: &str) -> BlobDescriptor;
fn insert_with_hash(
&mut self,
data: Vec<u8>,
hash: &str,
original_size: u64,
base_url: &str,
) -> BlobDescriptor {
let _ = (hash, original_size);
self.insert(data, base_url)
}
fn get(&self, sha256: &str) -> Option<Vec<u8>>;
fn exists(&self, sha256: &str) -> bool;
fn delete(&mut self, sha256: &str) -> bool;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn total_bytes(&self) -> u64;
fn insert_stream(
&mut self,
reader: &mut dyn std::io::Read,
size: u64,
base_url: &str,
) -> Result<BlobDescriptor, String> {
let mut data = Vec::with_capacity(size as usize);
reader
.read_to_end(&mut data)
.map_err(|e| format!("read stream: {e}"))?;
Ok(self.insert(data, base_url))
}
}
pub(crate) fn make_descriptor(data: &[u8], base_url: &str) -> BlobDescriptor {
let hash = crate::protocol::sha256_hex(data);
make_descriptor_from_hash(&hash, data.len() as u64, base_url)
}
pub(crate) fn make_descriptor_from_hash(hash: &str, size: u64, base_url: &str) -> BlobDescriptor {
let url = format!("{}/{}", base_url, hash);
let ts = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
BlobDescriptor {
sha256: hash.to_string(),
size,
content_type: Some("application/octet-stream".into()),
url: Some(url),
uploaded: Some(ts),
}
}