use std::{ collections::HashMap, fmt::{self, Display}, }; use thiserror::Error; #[derive(Debug, Error)] enum Error { #[error("Asset could not be found: {0}")] AssetNotFound(AssetId), } #[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct AssetId(String); impl Display for AssetId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "AssetId({}", self.0) } } impl From<&str> for AssetId { fn from(s: &str) -> Self { AssetId(s.to_owned()) } } pub trait Assets { fn assets(&self) -> Vec; fn get(&self, asset_id: AssetId) -> Result, Error>; } pub struct FsAssets { assets: HashMap, } impl FsAssets { pub fn new() -> Self { Self { assets: HashMap::new(), } } fn assets<'a>(&'a self) -> impl Iterator { self.assets.keys() } } impl Assets for FsAssets { fn assets(&self) -> Vec { self.assets.keys().cloned().collect() } fn get(&self, asset_id: AssetId) -> Result, Error> { unimplemented!() } } #[cfg(test)] pub mod mocks { use std::collections::HashMap; use super::*; pub struct MemoryAssets { assets: HashMap, } impl MemoryAssets { pub fn new(data: Vec<(AssetId, String)>) -> Self { let mut m = HashMap::new(); data.into_iter().for_each(|(asset, path)| { m.insert(asset, path); }); Self { assets: m } } } impl Assets for MemoryAssets { fn assets(&self) -> Vec { self.assets.keys().cloned().collect() } fn get(&self, asset_id: AssetId) -> Result, Error> { unimplemented!() } } }