1use keket::{
2 database::{
3 inspector::AssetInspector,
4 path::AssetPathStatic,
5 reference::{AssetRef, SmartAssetRef},
6 },
7 protocol::bundle::{
8 BundleWithDependencies, BundleWithDependenciesProcessor, StoreWithDependencies,
9 },
10 third_party::anput::component::Component,
11};
12use std::{
13 error::Error,
14 ops::{Deref, DerefMut},
15};
16
17pub trait AssetTree: Component {
22 fn asset_dependencies(&self) -> impl IntoIterator<Item = AssetPathStatic>;
30}
31
32impl<T: AssetTree> AssetTree for Option<T> {
33 fn asset_dependencies(&self) -> impl IntoIterator<Item = AssetPathStatic> {
34 self.as_ref()
35 .into_iter()
36 .flat_map(|asset| asset.asset_dependencies())
37 }
38}
39
40impl AssetTree for AssetPathStatic {
41 fn asset_dependencies(&self) -> impl IntoIterator<Item = AssetPathStatic> {
42 std::iter::once(self.clone().into_static())
43 }
44}
45
46impl AssetTree for AssetRef {
47 fn asset_dependencies(&self) -> impl IntoIterator<Item = AssetPathStatic> {
48 std::iter::once(self.path().clone().into_static())
49 }
50}
51
52impl AssetTree for SmartAssetRef {
53 fn asset_dependencies(&self) -> impl IntoIterator<Item = AssetPathStatic> {
54 std::iter::once(self.path().clone().into_static())
55 }
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
63#[repr(transparent)]
64pub struct NoDeps<T: Component>(pub T);
65
66impl<T: Component> Deref for NoDeps<T> {
67 type Target = T;
68
69 fn deref(&self) -> &Self::Target {
70 &self.0
71 }
72}
73
74impl<T: Component> DerefMut for NoDeps<T> {
75 fn deref_mut(&mut self) -> &mut Self::Target {
76 &mut self.0
77 }
78}
79
80impl<T: Component> AssetTree for NoDeps<T> {
81 fn asset_dependencies(&self) -> impl IntoIterator<Item = AssetPathStatic> {
82 []
83 }
84}
85
86pub struct AssetTreeProcessor<T: AssetTree> {
91 #[allow(clippy::type_complexity)]
92 deserializer: Box<dyn FnMut(Vec<u8>) -> Result<T, Box<dyn Error>> + Send + Sync>,
93 #[allow(clippy::type_complexity)]
94 serializer: Option<Box<dyn FnMut(&T) -> Result<Vec<u8>, Box<dyn Error>> + Send + Sync>>,
95}
96
97impl<T: AssetTree> AssetTreeProcessor<T> {
98 pub fn new(
110 deserializer: impl FnMut(Vec<u8>) -> Result<T, Box<dyn Error>> + Send + Sync + 'static,
111 ) -> Self {
112 Self {
113 deserializer: Box::new(deserializer),
114 serializer: None,
115 }
116 }
117
118 pub fn with_serializer(
131 mut self,
132 serializer: impl FnMut(&T) -> Result<Vec<u8>, Box<dyn Error>> + Send + Sync + 'static,
133 ) -> Self {
134 self.serializer = Some(Box::new(serializer));
135 self
136 }
137}
138
139impl<T: AssetTree> BundleWithDependenciesProcessor for AssetTreeProcessor<T> {
140 type Bundle = (T,);
141
142 fn process_bytes(
143 &mut self,
144 bytes: Vec<u8>,
145 ) -> Result<BundleWithDependencies<Self::Bundle>, Box<dyn Error>> {
146 let asset = (self.deserializer)(bytes)?;
147 let dependencies = T::asset_dependencies(&asset)
148 .into_iter()
149 .collect::<Vec<_>>();
150 let mut result = BundleWithDependencies::new((asset,));
151 result.dependencies = dependencies;
152 Ok(result)
153 }
154
155 fn produce_bytes(
156 &mut self,
157 inspector: AssetInspector,
158 ) -> Result<StoreWithDependencies, Box<dyn Error>> {
159 let Some(serializer) = self.serializer.as_mut() else {
160 return Err(format!(
161 "Serializer is not set for AssetTreeProcessor<{}>",
162 std::any::type_name::<T>(),
163 )
164 .into());
165 };
166 let component = inspector.access_checked::<&T>().ok_or_else(|| {
167 format!(
168 "Could not get {} asset component",
169 std::any::type_name::<T>(),
170 )
171 })?;
172 let bytes = (serializer)(component)?;
173 let dependencies = T::asset_dependencies(component)
174 .into_iter()
175 .collect::<Vec<_>>();
176 let mut result = StoreWithDependencies::new(bytes);
177 result.dependencies = dependencies;
178 Ok(result)
179 }
180}