use std::fs;
use std::path::{Path, PathBuf};
use crate::manifest::Manifest;
use crate::{Error, Result};
const MANIFEST: &str = "manifest.json";
const SEGMENTS_DIR: &str = "segments";
pub struct LocalStore {
root: PathBuf,
}
impl LocalStore {
pub fn open(root: impl AsRef<Path>) -> Result<Self> {
let root = root.as_ref().to_path_buf();
fs::create_dir_all(root.join(SEGMENTS_DIR))?;
Ok(Self { root })
}
pub fn load_manifest(&self) -> Result<Option<Manifest>> {
let path = self.root.join(MANIFEST);
let bytes = match fs::read(&path) {
Ok(b) => b,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(None),
Err(e) => return Err(e.into()),
};
let manifest = serde_json::from_slice(&bytes)
.map_err(|e| Error::CorruptManifest(e.to_string()))?;
Ok(Some(manifest))
}
pub fn commit_manifest(&self, manifest: &Manifest) -> Result<()> {
let tmp = self.root.join(format!("{MANIFEST}.tmp"));
let bytes = serde_json::to_vec_pretty(manifest)
.map_err(|e| Error::CorruptManifest(e.to_string()))?;
fs::write(&tmp, bytes)?;
fs::rename(&tmp, self.root.join(MANIFEST))?;
Ok(())
}
pub fn write_segment(&self, name: &str, bytes: &[u8]) -> Result<()> {
fs::write(self.root.join(SEGMENTS_DIR).join(name), bytes)?;
Ok(())
}
pub fn read_segment(&self, name: &str) -> Result<Vec<u8>> {
Ok(fs::read(self.root.join(SEGMENTS_DIR).join(name))?)
}
}