use crate::{Actor, ActorBehavior, Message, Port};
use anyhow::{Error, Result};
use reflow_actor::{message::EncodableValue, ActorContext};
use reflow_actor_macro::actor;
use serde_json::{json, Value};
use std::collections::HashMap;
#[actor(
FontLoadActor,
inports::<10>(font_data, tick),
outports::<1>(font_data, metadata),
state(MemoryState)
)]
pub async fn font_load_actor(ctx: ActorContext) -> Result<HashMap<String, Message>, Error> {
let payload = ctx.get_payload();
let config = ctx.get_config_hashmap();
if let Some(Message::Bytes(bytes)) = payload.get("font_data") {
let data = bytes.to_vec();
ctx.pool_upsert("_font", "loaded", json!(true));
ctx.pool_upsert("_font", "size", json!(data.len()));
let mut out = HashMap::new();
out.insert("font_data".to_string(), Message::bytes(data));
return Ok(out);
}
let is_loaded = ctx
.get_pool("_font")
.into_iter()
.any(|(k, v)| k == "loaded" && v == json!(true));
if !is_loaded {
let font_bytes = load_font_bytes(&config)?;
let size = font_bytes.len();
ctx.pool_upsert("_font", "loaded", json!(true));
ctx.pool_upsert("_font", "size", json!(size));
let source = config
.get("path")
.and_then(|v| v.as_str())
.or_else(|| config.get("font").and_then(|v| v.as_str()))
.unwrap_or("unknown");
let mut out = HashMap::new();
out.insert("font_data".to_string(), Message::bytes(font_bytes));
out.insert(
"metadata".to_string(),
Message::object(EncodableValue::from(json!({
"source": source,
"size": size,
}))),
);
return Ok(out);
}
Ok(HashMap::new())
}
fn load_font_bytes(config: &HashMap<String, Value>) -> Result<Vec<u8>> {
if let Some(path) = config.get("path").and_then(|v| v.as_str()) {
return std::fs::read(path)
.map_err(|e| anyhow::anyhow!("Failed to read font file '{}': {}", path, e));
}
if let Some(font_id) = config.get("font").and_then(|v| v.as_str()) {
if let Some(db_path) = config.get("$db").and_then(|v| v.as_str()) {
let db = reflow_assets::get_or_create_db(db_path)?;
if let Ok(asset) = db.get(font_id) {
return Ok(asset.data);
}
}
}
Err(anyhow::anyhow!(
"No font source configured. Set 'path' or 'font' + '$db' in config."
))
}