use assets_manager::{
AssetCache, BoxedError,
hot_reloading::{EventSender, FsWatcherBuilder},
source::{DirEntry, FileContent, FileSystem, Source},
};
use std::{
io,
path::{Path, PathBuf},
};
#[derive(Debug, Clone)]
pub struct FsWithOverride {
default_dir: FileSystem,
override_dir: Option<FileSystem>,
}
impl FsWithOverride {
pub fn new<P: AsRef<Path>>(default_path: P) -> io::Result<Self> {
let default_dir = FileSystem::new(default_path)?;
let override_dir = std::env::var_os("ASSETS_OVERRIDE").and_then(|path| {
FileSystem::new(path)
.map_err(|err| log::error!("Error setting override assets directory: {err}"))
.ok()
});
Ok(Self {
default_dir,
override_dir,
})
}
pub fn path_of(&self, specifier: &str, ext: &str) -> PathBuf {
self.default_dir.path_of(DirEntry::File(specifier, ext))
}
}
impl Source for FsWithOverride {
fn read(&self, id: &str, ext: &str) -> io::Result<FileContent<'_>> {
if let Some(dir) = &self.override_dir {
match dir.read(id, ext) {
Ok(content) => return Ok(content),
Err(err) => {
if err.kind() != io::ErrorKind::NotFound {
let path = dir.path_of(DirEntry::File(id, ext));
log::warn!("Error reading \"{}\": {err}", path.display());
}
}
}
}
self.default_dir.read(id, ext)
}
fn read_dir(&self, id: &str, f: &mut dyn FnMut(DirEntry)) -> io::Result<()> {
if let Some(dir) = &self.override_dir {
match dir.read_dir(id, f) {
Ok(()) => return Ok(()),
Err(err) => {
if err.kind() != io::ErrorKind::NotFound {
let path = dir.path_of(DirEntry::Directory(id));
log::warn!("Error reading \"{}\": {}", path.display(), err);
}
}
}
}
self.default_dir.read_dir(id, f)
}
fn exists(&self, entry: DirEntry) -> bool {
self.override_dir
.as_ref()
.map_or(false, |dir| dir.exists(entry))
|| self.default_dir.exists(entry)
}
fn configure_hot_reloading(&self, events: EventSender) -> Result<(), BoxedError> {
let mut builder = FsWatcherBuilder::new()?;
if let Some(dir) = &self.override_dir {
builder.watch(dir.root().to_owned())?;
}
builder.watch(self.default_dir.root().to_owned())?;
builder.build(events);
Ok(())
}
}
fn main() -> Result<(), BoxedError> {
env_logger::builder()
.filter_level(log::LevelFilter::Info)
.init();
let source = FsWithOverride::new("assets")?;
let cache = AssetCache::with_source(source);
let msg = cache.load::<String>("example.hello")?;
loop {
println!("{}", msg.read());
std::thread::sleep(std::time::Duration::from_secs(1))
}
}