use crate::{SharedUri, WindowContext}; use collections::FxHashMap; use futures::Future; use parking_lot::Mutex; use std::any::TypeId; use std::hash::{Hash, Hasher}; use std::sync::Arc; use std::{any::Any, path::PathBuf}; #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub(crate) enum UriOrPath { Uri(SharedUri), Path(Arc), } impl From for UriOrPath { fn from(value: SharedUri) -> Self { Self::Uri(value) } } impl From> for UriOrPath { fn from(value: Arc) -> Self { Self::Path(value) } } /// A trait for asynchronous asset loading. pub trait Asset { /// The source of the asset. type Source: Clone + Hash + Send; /// The loaded asset type Output: Clone + Send; /// Load the asset asynchronously fn load( source: Self::Source, cx: &mut WindowContext, ) -> impl Future + Send + 'static; } /// Use a quick, non-cryptographically secure hash function to get an identifier from data pub fn hash(data: &T) -> u64 { let mut hasher = collections::FxHasher::default(); data.hash(&mut hasher); hasher.finish() } /// A cache for assets. #[derive(Clone)] pub struct AssetCache { assets: Arc>>>, } impl AssetCache { pub(crate) fn new() -> Self { Self { assets: Default::default(), } } /// Get the asset from the cache, if it exists. pub fn get(&self, source: &A::Source) -> Option { self.assets .lock() .get(&(TypeId::of::(), hash(&source))) .and_then(|task| task.downcast_ref::()) .cloned() } /// Insert the asset into the cache. pub fn insert(&mut self, source: A::Source, output: A::Output) { self.assets .lock() .insert((TypeId::of::(), hash(&source)), Box::new(output)); } /// Remove an entry from the asset cache pub fn remove(&mut self, source: &A::Source) -> Option { self.assets .lock() .remove(&(TypeId::of::(), hash(&source))) .and_then(|any| any.downcast::().ok()) .map(|boxed| *boxed) } }