1use crate::{App, SharedString, SharedUri};
2use futures::{Future, TryFutureExt};
3
4use std::fmt::Debug;
5use std::hash::{Hash, Hasher};
6use std::marker::PhantomData;
7use std::path::{Path, PathBuf};
8use std::sync::Arc;
9
10#[derive(Debug, PartialEq, Eq, Hash, Clone)]
12pub enum Resource {
13 Uri(SharedUri),
15 Path(Arc<Path>),
17 Embedded(SharedString),
19}
20
21impl From<SharedUri> for Resource {
22 fn from(value: SharedUri) -> Self {
23 Self::Uri(value)
24 }
25}
26
27impl From<PathBuf> for Resource {
28 fn from(value: PathBuf) -> Self {
29 Self::Path(value.into())
30 }
31}
32
33impl From<Arc<Path>> for Resource {
34 fn from(value: Arc<Path>) -> Self {
35 Self::Path(value)
36 }
37}
38
39pub trait Asset: 'static {
41 type Source: Clone + Hash + Send;
43
44 type Output: Clone + Send;
46
47 fn load(
49 source: Self::Source,
50 cx: &mut App,
51 ) -> impl Future<Output = Self::Output> + Send + 'static;
52}
53
54pub enum AssetLogger<T> {
56 #[doc(hidden)]
57 _Phantom(PhantomData<T>, &'static dyn crate::seal::Sealed),
58}
59
60impl<T, R, E> Asset for AssetLogger<T>
61where
62 T: Asset<Output = Result<R, E>>,
63 R: Clone + Send,
64 E: Clone + Send + std::fmt::Display,
65{
66 type Source = T::Source;
67
68 type Output = T::Output;
69
70 fn load(
71 source: Self::Source,
72 cx: &mut App,
73 ) -> impl Future<Output = Self::Output> + Send + 'static {
74 let load = T::load(source, cx);
75 load.inspect_err(|e| log::error!("Failed to load asset: {}", e))
76 }
77}
78
79pub fn hash<T: Hash>(data: &T) -> u64 {
81 let mut hasher = collections::FxHasher::default();
82 data.hash(&mut hasher);
83 hasher.finish()
84}