use crate::Dialect;
use evy_ecs_storage::ParticleId;
#[derive(Debug, Clone, Copy)]
pub struct FieldSignature {
pub name: &'static str,
pub type_name: &'static str,
}
impl FieldSignature {
pub const fn new(name: &'static str, type_name: &'static str) -> Self {
Self { name, type_name }
}
}
pub fn dialect_from_signature(signature: &str) -> Dialect {
let h = hemera::hash(signature.as_bytes());
ParticleId::from_hash(*h.as_bytes())
}
pub fn dialect_from_struct(name: &str, fields: &[FieldSignature]) -> Dialect {
let mut sig = String::with_capacity(name.len() + 16 + fields.len() * 16);
sig.push_str("struct ");
sig.push_str(name);
sig.push('{');
for (i, f) in fields.iter().enumerate() {
if i > 0 {
sig.push(',');
}
sig.push_str(f.name);
sig.push(':');
sig.push_str(f.type_name);
}
sig.push('}');
dialect_from_signature(&sig)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn same_signature_yields_same_dialect() {
let a = dialect_from_signature("foo");
let b = dialect_from_signature("foo");
assert_eq!(a, b);
}
#[test]
fn different_signatures_yield_different_dialects() {
let a = dialect_from_signature("foo");
let b = dialect_from_signature("bar");
assert_ne!(a, b);
}
#[test]
fn struct_dialect_is_field_order_sensitive() {
let a = dialect_from_struct(
"Point",
&[FieldSignature::new("x", "f32"), FieldSignature::new("y", "f32")],
);
let b = dialect_from_struct(
"Point",
&[FieldSignature::new("y", "f32"), FieldSignature::new("x", "f32")],
);
assert_ne!(a, b);
}
#[test]
fn struct_dialect_is_type_sensitive() {
let a = dialect_from_struct(
"Point",
&[FieldSignature::new("x", "f32"), FieldSignature::new("y", "f32")],
);
let b = dialect_from_struct(
"Point",
&[FieldSignature::new("x", "f64"), FieldSignature::new("y", "f64")],
);
assert_ne!(a, b);
}
#[test]
fn struct_dialect_is_name_sensitive() {
let a = dialect_from_struct(
"Point",
&[FieldSignature::new("x", "f32"), FieldSignature::new("y", "f32")],
);
let b = dialect_from_struct(
"Vec2",
&[FieldSignature::new("x", "f32"), FieldSignature::new("y", "f32")],
);
assert_ne!(a, b);
}
#[test]
fn empty_struct_has_distinct_dialect() {
let a = dialect_from_struct("Marker", &[]);
let b = dialect_from_struct("Marker", &[FieldSignature::new("v", "()")]);
assert_ne!(a, b);
}
}