use crate::FieldDelta;
use std::sync::OnceLock;
pub type DiffFn = Box<dyn Fn(&[u8], &[u8]) -> Vec<FieldDelta> + Send + Sync>;
pub struct AccountSchema {
pub type_name: String,
pub discriminator: Vec<u8>,
pub diff_fn: DiffFn,
}
static SCHEMA_REGISTRY: OnceLock<Vec<AccountSchema>> = OnceLock::new();
pub fn register_account_schemas(schemas: Vec<AccountSchema>) {
let _ = SCHEMA_REGISTRY.set(schemas);
}
pub fn lookup_diff_fn(data: &[u8]) -> Option<&DiffFn> {
let registry = SCHEMA_REGISTRY.get()?;
for schema in registry {
if data.len() >= schema.discriminator.len()
&& data[..schema.discriminator.len()] == schema.discriminator[..]
{
return Some(&schema.diff_fn);
}
}
None
}
pub fn lookup_type_name(data: &[u8]) -> Option<&str> {
let registry = SCHEMA_REGISTRY.get()?;
for schema in registry {
if data.len() >= schema.discriminator.len()
&& data[..schema.discriminator.len()] == schema.discriminator[..]
{
return Some(&schema.type_name);
}
}
None
}
pub fn has_schemas() -> bool {
SCHEMA_REGISTRY
.get()
.map(|r| !r.is_empty())
.unwrap_or(false)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lookup_no_registry() {
let result = lookup_diff_fn(&[0u8; 16]);
assert!(result.is_none() || result.is_some());
}
}