use keket::{
database::{AssetDatabase, path::AssetPathStatic},
fetch::file::FileAssetFetch,
protocol::bundle::{
BundleAssetProtocol, BundleWithDependencies, BundleWithDependenciesProcessor,
},
};
use serde::Deserialize;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let mut database = AssetDatabase::default()
.with_protocol(BundleAssetProtocol::new("custom", CustomAssetProcessor))
.with_fetch(FileAssetFetch::default().with_root("resources"));
let handle = database.ensure("custom://part1.json")?;
while database.is_busy() {
database.maintain()?;
}
let contents = handle.access::<&CustomAsset>(&database).contents(&database);
println!("Custom chain contents: {contents:?}");
Ok(())
}
#[derive(Debug, Default, Deserialize)]
struct CustomAsset {
content: String,
#[serde(default)]
next: Option<AssetPathStatic>,
}
impl CustomAsset {
fn contents(&self, database: &AssetDatabase) -> String {
let mut result = String::new();
let mut current = Some(self);
while let Some(asset) = current {
result.push_str(asset.content.as_str());
current = current
.as_ref()
.and_then(|asset| asset.next.as_ref())
.and_then(|path| path.find(database))
.and_then(|handle| handle.access_checked::<&Self>(database));
if current.is_some() {
result.push(' ');
}
}
result
}
}
struct CustomAssetProcessor;
impl BundleWithDependenciesProcessor for CustomAssetProcessor {
type Bundle = (CustomAsset,);
fn process_bytes(
&mut self,
bytes: Vec<u8>,
) -> Result<BundleWithDependencies<Self::Bundle>, Box<dyn Error>> {
let asset = serde_json::from_slice::<CustomAsset>(&bytes)?;
let dependency = asset.next.clone();
Ok(BundleWithDependencies::new((asset,)).maybe_dependency(dependency))
}
}