use super::StorageBackend; use crate::server::blobref::BlobRef; use crate::server::storage::{Error, Result}; use log::debug; use serde::{Deserialize, Serialize}; use std::{fs, io::ErrorKind, path::PathBuf}; pub struct Disk { bucket: String, pub root: PathBuf, } #[derive(Serialize, Deserialize)] pub struct Config { pub root: PathBuf, } impl StorageBackend for Disk { type Config = Config; fn new(bucket: &str, config: &Self::Config) -> Self { Self { bucket: bucket.to_string(), root: config.root.clone().join(bucket), } } fn put(&self, data: &[u8]) -> Result { let blobref = BlobRef::for_bytes(data); debug!("Preparing {blobref}"); if !self.exists(&blobref) { let blobpath = self.root.join(blobref.path()); let blobdir = blobpath.parent().expect("blobpath should have a parent"); debug!("Writing blob to {blobpath:?}"); fs::create_dir_all(blobdir).map_err(|_| Error::Io)?; fs::write(blobpath, data).map_err(|_| Error::Io)?; } Ok(blobref) } fn get(&self, blobref: &BlobRef) -> Result>> { let blobpath = self.root.join(blobref.path()); match fs::read(blobpath) { Ok(contents) => Ok(Some(contents)), Err(e) if e.kind() == ErrorKind::NotFound => Ok(None), Err(e) => Err(Error::Io), } } fn exists(&self, blobref: &BlobRef) -> bool { self.root.join(blobref.path()).exists() } } impl Iterator for Disk { type Item = BlobRef; fn next(&mut self) -> Option { todo!() } }