1use std::fs;
6use std::path::{Path, PathBuf};
7
8use crate::manifest::Manifest;
9use crate::{Error, Result};
10
11const MANIFEST: &str = "manifest.json";
12const SEGMENTS_DIR: &str = "segments";
13
14pub struct LocalStore {
15 root: PathBuf,
16}
17
18impl LocalStore {
19 pub fn open(root: impl AsRef<Path>) -> Result<Self> {
20 let root = root.as_ref().to_path_buf();
21 fs::create_dir_all(root.join(SEGMENTS_DIR))?;
22 Ok(Self { root })
23 }
24
25 pub fn load_manifest(&self) -> Result<Option<Manifest>> {
26 let path = self.root.join(MANIFEST);
27 let bytes = match fs::read(&path) {
28 Ok(b) => b,
29 Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(None),
30 Err(e) => return Err(e.into()),
31 };
32 let manifest = serde_json::from_slice(&bytes)
33 .map_err(|e| Error::CorruptManifest(e.to_string()))?;
34 Ok(Some(manifest))
35 }
36
37 pub fn commit_manifest(&self, manifest: &Manifest) -> Result<()> {
41 let tmp = self.root.join(format!("{MANIFEST}.tmp"));
42 let bytes = serde_json::to_vec_pretty(manifest)
43 .map_err(|e| Error::CorruptManifest(e.to_string()))?;
44 fs::write(&tmp, bytes)?;
45 fs::rename(&tmp, self.root.join(MANIFEST))?;
46 Ok(())
47 }
48
49 pub fn write_segment(&self, name: &str, bytes: &[u8]) -> Result<()> {
53 fs::write(self.root.join(SEGMENTS_DIR).join(name), bytes)?;
54 Ok(())
55 }
56
57 pub fn read_segment(&self, name: &str) -> Result<Vec<u8>> {
58 Ok(fs::read(self.root.join(SEGMENTS_DIR).join(name))?)
59 }
60}