87 lines · 2.3 KB · Rust
RawDownload
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<PathBuf>),} impl From<SharedUri> for UriOrPath {    fn from(value: SharedUri) -> Self {        Self::Uri(value)    }} impl From<Arc<PathBuf>> for UriOrPath {    fn from(value: Arc<PathBuf>) -> 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<Output = Self::Output> + Send + 'static;} /// Use a quick, non-cryptographically secure hash function to get an identifier from datapub fn hash<T: 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<Mutex<FxHashMap<(TypeId, u64), Box<dyn Any + Send>>>>,} impl AssetCache {    pub(crate) fn new() -> Self {        Self {            assets: Default::default(),        }    }     /// Get the asset from the cache, if it exists.    pub fn get<A: Asset + 'static>(&self, source: &A::Source) -> Option<A::Output> {        self.assets            .lock()            .get(&(TypeId::of::<A>(), hash(&source)))            .and_then(|task| task.downcast_ref::<A::Output>())            .cloned()    }     /// Insert the asset into the cache.    pub fn insert<A: Asset + 'static>(&mut self, source: A::Source, output: A::Output) {        self.assets            .lock()            .insert((TypeId::of::<A>(), hash(&source)), Box::new(output));    }     /// Remove an entry from the asset cache    pub fn remove<A: Asset + 'static>(&mut self, source: &A::Source) -> Option<A::Output> {        self.assets            .lock()            .remove(&(TypeId::of::<A>(), hash(&source)))            .and_then(|any| any.downcast::<A::Output>().ok())            .map(|boxed| *boxed)    }}