Skip to main content

11_custom_protocol_simple/
11_custom_protocol_simple.rs

1use keket::{
2    database::{AssetDatabase, path::AssetPathStatic},
3    fetch::file::FileAssetFetch,
4    protocol::bundle::{
5        BundleAssetProtocol, BundleWithDependencies, BundleWithDependenciesProcessor,
6    },
7};
8use serde::Deserialize;
9use std::error::Error;
10
11fn main() -> Result<(), Box<dyn Error>> {
12    let mut database = AssetDatabase::default()
13        // Register custom asset processor.
14        .with_protocol(BundleAssetProtocol::new("custom", CustomAssetProcessor))
15        .with_fetch(FileAssetFetch::default().with_root("resources"));
16
17    // Ensure custom asset existence.
18    let handle = database.ensure("custom://part1.json")?;
19
20    // Make database process loaded dependencies.
21    while database.is_busy() {
22        database.maintain()?;
23    }
24
25    let contents = handle.access::<&CustomAsset>(&database).contents(&database);
26    println!("Custom chain contents: {contents:?}");
27
28    Ok(())
29}
30
31/* ANCHOR: custom_asset */
32// Custom asset type.
33#[derive(Debug, Default, Deserialize)]
34struct CustomAsset {
35    // Main content.
36    content: String,
37    // Optional sibling asset (content continuation).
38    #[serde(default)]
39    next: Option<AssetPathStatic>,
40}
41/* ANCHOR_END: custom_asset */
42
43impl CustomAsset {
44    fn contents(&self, database: &AssetDatabase) -> String {
45        // Read this and it's siblings content to output.
46        let mut result = String::new();
47        let mut current = Some(self);
48        while let Some(asset) = current {
49            result.push_str(asset.content.as_str());
50            current = current
51                .as_ref()
52                .and_then(|asset| asset.next.as_ref())
53                .and_then(|path| path.find(database))
54                .and_then(|handle| handle.access_checked::<&Self>(database));
55            if current.is_some() {
56                result.push(' ');
57            }
58        }
59        result
60    }
61}
62
63/* ANCHOR: custom_asset_protocol */
64struct CustomAssetProcessor;
65
66impl BundleWithDependenciesProcessor for CustomAssetProcessor {
67    // Bundle of asset components this asset processor produces from processed asset.
68    type Bundle = (CustomAsset,);
69
70    fn process_bytes(
71        &mut self,
72        bytes: Vec<u8>,
73    ) -> Result<BundleWithDependencies<Self::Bundle>, Box<dyn Error>> {
74        let asset = serde_json::from_slice::<CustomAsset>(&bytes)?;
75        let dependency = asset.next.clone();
76        // Return bundled components and optional dependency which will be additionally loaded.
77        Ok(BundleWithDependencies::new((asset,)).maybe_dependency(dependency))
78    }
79}
80/* ANCHOR_END: custom_asset_protocol */