use std::path::{Path, PathBuf};
use tracing::trace;
#[async_trait::async_trait]
pub trait TryLoad: Send + Sync {
type Error;
async fn try_load(path: &Path) -> Result<Self, Self::Error>
where
Self: Sized;
}
#[derive(Clone, Debug)]
pub enum LazyLoader<T>
where
T: TryLoad,
{
NotLoaded(PathBuf),
Loaded(T),
}
impl<T> LazyLoader<T>
where
T: TryLoad,
{
pub async fn try_load(&mut self) -> Result<&T, T::Error> {
match self {
LazyLoader::NotLoaded(path) => {
let path_clone = path.clone();
trace!(
"(lazy loader) attempting to load from path: {}",
path_clone.display()
);
let loaded = T::try_load(&path_clone).await?;
*self = LazyLoader::Loaded(loaded);
if let LazyLoader::Loaded(data) = self {
trace!(
"(lazy loader) loaded data from path: {}",
path_clone.display()
);
Ok(data)
} else {
unreachable!("Just set to Loaded, this should not happen")
}
}
LazyLoader::Loaded(data) => {
trace!("(lazy loader) returning cached value from lazy loader");
Ok(data)
}
}
}
}
impl<T> From<&Path> for LazyLoader<T>
where
T: TryLoad,
{
fn from(path: &Path) -> Self {
LazyLoader::NotLoaded(path.to_path_buf())
}
}