use std::path::{Path, PathBuf};
use onomancy_dnssec::{
certificate::Certificate,
statement::{rotation::RotationStatement, successor::SuccessorStatement},
};
use onomancy_protocol::verifier::state::store::{Store, item::Item};
pub(crate) fn load(dir: &Path) -> Result<Store, StoreDirError> {
std::fs::create_dir_all(dir)?;
let mut store = Store::default();
for entry in std::fs::read_dir(dir)? {
let path = entry?.path();
let Some(extension) = path.extension().and_then(|e| e.to_str()) else {
continue;
};
let item = match extension {
"onc" => Item::Record(Certificate::decode(&std::fs::read(&path)?).map_err(
|source| StoreDirError::Certificate {
path: path.clone(),
source,
},
)?),
"onr" => Item::Rotation(RotationStatement::decode(&std::fs::read(&path)?).map_err(
|source| StoreDirError::Rotation {
path: path.clone(),
source,
},
)?),
"ons" => Item::Successor(SuccessorStatement::decode(&std::fs::read(&path)?).map_err(
|source| StoreDirError::Successor {
path: path.clone(),
source,
},
)?),
_ => continue,
};
store.insert(item);
}
Ok(store)
}
pub(crate) fn persist(dir: &Path, item: &Item) -> Result<Option<PathBuf>, StoreDirError> {
let (extension, bytes) = match item {
Item::Record(certificate) => ("onc", certificate.encode()),
Item::Rotation(statement) => ("onr", statement.encode()),
Item::Successor(statement) => ("ons", statement.encode()),
Item::ChainRefresh { .. } => return Ok(None),
};
let path = dir.join(format!("{}.{extension}", item.content_hash()));
if !path.exists() {
std::fs::write(&path, bytes)?;
}
Ok(Some(path))
}
#[derive(Debug, thiserror::Error)]
pub(crate) enum StoreDirError {
#[error("store file {path}: {source}")]
Certificate {
path: PathBuf,
source: onomancy_dnssec::certificate::DecodeCertificateError,
},
#[error(transparent)]
Io(#[from] std::io::Error),
#[error("store file {path}: {source}")]
Rotation {
path: PathBuf,
source: onomancy_dnssec::statement::rotation::DecodeRotationError,
},
#[error("store file {path}: {source}")]
Successor {
path: PathBuf,
source: onomancy_dnssec::statement::successor::DecodeSuccessorError,
},
}