type AssetCacheMap =
std::collections::HashMap<String, cvkg_core::AssetState<std::sync::Arc<Vec<u8>>>>;
pub struct NativeAssetManager {
cache: std::sync::Arc<arc_swap::ArcSwap<AssetCacheMap>>,
}
impl Default for NativeAssetManager {
fn default() -> Self {
Self::new()
}
}
impl NativeAssetManager {
pub fn new() -> Self {
Self {
cache: std::sync::Arc::new(arc_swap::ArcSwap::from_pointee(
std::collections::HashMap::new(),
)),
}
}
}
impl cvkg_core::AssetManager for NativeAssetManager {
fn load_image(&self, url: &str) -> cvkg_core::AssetState<std::sync::Arc<Vec<u8>>> {
if let Some(state) = self.cache.load().get(url) {
return state.clone();
}
let cache = self.cache.clone();
let key = url.to_string();
let mut we_inserted = false;
self.cache.rcu(|map| {
if map.contains_key(&key) {
(**map).clone()
} else {
we_inserted = true;
let mut m = (**map).clone();
m.insert(key.clone(), cvkg_core::AssetState::Loading);
m
}
});
if we_inserted {
let cache_inner = cache.clone();
let key_inner = key.clone();
std::thread::spawn(move || {
tracing::debug!("[Native] Asynchronously loading asset: {}", key_inner);
let result = match std::fs::read(&key_inner) {
Ok(data) => cvkg_core::AssetState::Ready(std::sync::Arc::new(data)),
Err(e) => cvkg_core::AssetState::Error(e.to_string()),
};
cache_inner.rcu(move |map| {
let mut m = (**map).clone();
m.insert(key_inner.clone(), result.clone());
m
});
});
}
cvkg_core::AssetState::Loading
}
fn preload_image(&self, url: &str) {
if self.cache.load().contains_key(url) {
return;
}
let cache = self.cache.clone();
let key = url.to_string();
let mut we_inserted = false;
self.cache.rcu(|map| {
if map.contains_key(&key) {
(**map).clone()
} else {
we_inserted = true;
let mut m = (**map).clone();
m.insert(key.clone(), cvkg_core::AssetState::Loading);
m
}
});
if we_inserted {
std::thread::spawn(move || {
tracing::debug!("[Native] Preloading asset: {}", key);
let result = match std::fs::read(&key) {
Ok(data) => cvkg_core::AssetState::Ready(std::sync::Arc::new(data)),
Err(e) => cvkg_core::AssetState::Error(e.to_string()),
};
cache.rcu(move |map| {
let mut m = (**map).clone();
m.insert(key.clone(), result.clone());
m
});
});
}
}
}