extendable-assets

Asset framework for graphics and games.
Usage
Here's a basic example of using extendable-assets to manage texture assets:
use std::sync::Arc;
use extendable_assets::*;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct TextureData {
pub width: u32,
pub height: u32,
pub format: String,
pub pixels: Vec<u8>,
}
impl AssetData for TextureData {}
pub struct TextureAssetType;
impl AssetType for TextureAssetType {
fn name(&self) -> &str {
"Texture"
}
fn loader(&self) -> Box<dyn AssetDataLoader> {
struct TextureLoader;
impl AssetDataLoader for TextureLoader {
fn asset_from_bytes(
&self,
bytes: &[u8],
_context: Option<Arc<dyn AssetManagerContext>>,
) -> Result<Box<dyn AssetData>, AssetLoadError> {
let data: TextureData = serde_json::from_slice(bytes)
.map_err(|e| AssetLoadError::Deserialization(anyhow::Error::new(e)))?;
Ok(Box::new(data))
}
}
Box::new(TextureLoader)
}
fn saver(&self) -> Box<dyn AssetDataSaver> {
struct TextureSaver;
impl AssetDataSaver for TextureSaver {
fn asset_to_bytes(
&self,
asset: &dyn AssetData,
_context: Option<Arc<dyn AssetManagerContext>>,
) -> Result<Vec<u8>, AssetSaveError> {
let data = asset
.downcast_ref::<TextureData>()
.ok_or(AssetSaveError::UnsupportedType)?;
serde_json::to_vec(&data)
.map_err(|e| AssetSaveError::Serialization(anyhow::Error::new(e)))
}
}
Box::new(TextureSaver)
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut manager = AssetManager::new(Arc::new(NativeFilesystem::new("assets")));
manager.set_serialization_backend(Box::new(JsonAssetSerializationBackend));
manager.register_asset_type(Arc::new(TextureAssetType));
let texture_data = TextureData {
width: 256,
height: 256,
format: "RGBA8".to_string(),
pixels: vec![255; 256 * 256 * 4],
};
let asset_type = manager.asset_type_by_name("Texture").unwrap();
let asset = Asset::new(asset_type, Box::new(texture_data));
let asset_id = manager.register_asset("my_texture", asset);
let loaded_id = manager.fs_read_and_register_asset("textures/grass.json").await?;
let loaded_asset = manager.asset_by_id(loaded_id).unwrap();
if let Some(texture) = loaded_asset.data().downcast_ref::<TextureData>() {
println!("Loaded texture: {}x{} ({})", texture.width, texture.height, texture.format);
}
Ok(())
}
Key Features
- Type-safe asset system: Define custom asset types with compile-time safety
- Multiple filesystem backends: Native filesystem, embedded assets, or custom implementations
- Flexible serialization: JSON, MessagePack, or custom serialization backends
- Async I/O: Non-blocking asset loading and saving operations
- Deterministic IDs: Hash-based asset IDs for consistent references
- Extensible: Easy to add new asset types and storage backends
AI Disclosure
Generative AI has been used to assist in writing documentation and commit messages. The code
in this project has been written by a human.