use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Mutex;
#[derive(Debug, Clone)]
pub enum AssetSource {
Path(PathBuf),
Bytes(Vec<u8>),
Url(String),
}
impl AssetSource {
pub fn path<P: Into<PathBuf>>(path: P) -> Self {
Self::Path(path.into())
}
pub fn bytes(bytes: Vec<u8>) -> Self {
Self::Bytes(bytes)
}
pub fn url(url: String) -> Self {
Self::Url(url)
}
pub fn as_bytes(&self) -> Option<&[u8]> {
match self {
Self::Bytes(bytes) => Some(bytes),
_ => None,
}
}
}
pub trait AssetResolver: Send + Sync {
fn resolve(&self, src: &str) -> Result<AssetSource, String>;
}
pub struct PathAssetResolver;
impl AssetResolver for PathAssetResolver {
fn resolve(&self, src: &str) -> Result<AssetSource, String> {
Ok(AssetSource::Path(PathBuf::from(src)))
}
}
pub struct MemoryAssetResolver {
assets: Mutex<HashMap<String, Vec<u8>>>,
}
impl MemoryAssetResolver {
pub fn new() -> Self {
Self {
assets: Mutex::new(HashMap::new()),
}
}
pub fn insert(&self, src: String, bytes: Vec<u8>) {
self.assets
.lock()
.expect("memory asset lock")
.insert(src, bytes);
}
pub fn clear(&self) {
self.assets.lock().expect("memory asset lock").clear();
}
pub fn with_asset(self, src: String, bytes: Vec<u8>) -> Self {
self.insert(src, bytes);
self
}
}
impl Default for MemoryAssetResolver {
fn default() -> Self {
Self::new()
}
}
impl AssetResolver for MemoryAssetResolver {
fn resolve(&self, src: &str) -> Result<AssetSource, String> {
self.assets
.lock()
.expect("memory asset lock")
.get(src)
.cloned()
.map(AssetSource::Bytes)
.ok_or_else(|| format!("asset not found in memory resolver: {src}"))
}
}
impl Default for PathAssetResolver {
fn default() -> Self {
Self
}
}