use crate::error::CacheError;
use dig_store::{Bytes32, CapsuleIdentity};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
pub const MANIFEST_VERSION: u32 = 1;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Manifest {
pub version: u32,
pub next_seq: u64,
pub entries: Vec<ManifestEntry>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ManifestEntry {
pub store_id: String,
pub root_hash: String,
pub retrieval_key: String,
pub size: u64,
pub seq: u64,
pub pinned: bool,
}
impl ManifestEntry {
pub fn identity(&self) -> Option<CapsuleIdentity> {
Some(CapsuleIdentity {
store_id: hex_to_bytes32(&self.store_id)?,
root_hash: hex_to_bytes32(&self.root_hash)?,
})
}
}
pub fn load(root: &Path) -> Option<Manifest> {
let path = crate::layout::manifest_path(root);
let raw = fs::read(&path).ok()?;
serde_json::from_slice(&raw).ok()
}
pub fn save(root: &Path, manifest: &Manifest) -> Result<(), CacheError> {
let path = crate::layout::manifest_path(root);
let tmp = path.with_extension("json.tmp");
let json = serde_json::to_vec_pretty(manifest).expect("manifest serializes");
{
use std::io::Write;
let mut file = fs::File::create(&tmp).map_err(|e| CacheError::io(&tmp, e))?;
file.write_all(&json).map_err(|e| CacheError::io(&tmp, e))?;
file.sync_all().map_err(|e| CacheError::io(&tmp, e))?;
}
fs::rename(&tmp, &path).map_err(|e| CacheError::io(&path, e))
}
pub fn bytes32_hex(value: &Bytes32) -> String {
hex::encode(value.as_slice())
}
fn hex_to_bytes32(s: &str) -> Option<Bytes32> {
let bytes = hex::decode(s).ok()?;
let array: [u8; 32] = bytes.try_into().ok()?;
Some(Bytes32::new(array))
}