use std::path::Path;
use fs_mistrust::CheckedDir;
use serde::{Serialize, de::DeserializeOwned};
use tor_error::ErrorReport as _;
use tracing::trace;
use crate::err::ErrorSource;
#[derive(derive_more::Display)]
#[display("{:?}/{:?}", dir.as_path(), rel_fname)]
pub(crate) struct Target<'r> {
pub(crate) dir: &'r CheckedDir,
pub(crate) rel_fname: &'r Path,
}
impl Target<'_> {
pub(crate) fn load<D: DeserializeOwned>(&self) -> Result<Option<D>, ErrorSource> {
let string = match self.dir.read_to_string(self.rel_fname) {
Ok(string) => string,
Err(fs_mistrust::Error::NotFound(_)) => {
trace!("loading {self} (not found)");
return Ok(None);
}
Err(e) => {
trace!("loading {self}, error {}", e.report());
return Err(e.into());
}
};
let r = serde_json::from_str(&string)?;
trace!("loaded {self}");
Ok(Some(r))
}
pub(crate) fn store<S: Serialize>(&self, val: &S) -> Result<(), ErrorSource> {
trace!("storing {self}");
let output = serde_json::to_string_pretty(val)?;
self.dir.write_and_replace(self.rel_fname, output)?;
Ok(())
}
pub(crate) fn delete(&self) -> Result<(), ErrorSource> {
trace!("deleting {self}");
self.dir.remove_file(self.rel_fname)?;
Ok(())
}
}