use crate::{App, SharedString, SharedUri}; use futures::{Future, TryFutureExt}; use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::path::{Path, PathBuf}; use std::sync::Arc; /// An enum representing #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum Resource { /// This resource is at a given URI Uri(SharedUri), /// This resource is at a given path in the file system Path(Arc), /// This resource is embedded in the application binary Embedded(SharedString), } impl From for Resource { fn from(value: SharedUri) -> Self { Self::Uri(value) } } impl From for Resource { fn from(value: PathBuf) -> Self { Self::Path(value.into()) } } impl From> for Resource { fn from(value: Arc) -> Self { Self::Path(value) } } /// A trait for asynchronous asset loading. pub trait Asset: 'static { /// 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 App, ) -> impl Future + Send + 'static; } /// An asset Loader which logs the [`Err`] variant of a [`Result`] during loading pub enum AssetLogger { #[doc(hidden)] _Phantom(PhantomData, &'static dyn crate::seal::Sealed), } impl Asset for AssetLogger where T: Asset>, R: Clone + Send, E: Clone + Send + std::fmt::Display, { type Source = T::Source; type Output = T::Output; fn load( source: Self::Source, cx: &mut App, ) -> impl Future + Send + 'static { let load = T::load(source, cx); load.inspect_err(|e| log::error!("Failed to load asset: {}", e)) } } /// 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() }