terminals-core 0.1.0

Core runtime primitives for Terminals OS: phase dynamics, AXON wire protocol, substrate engine, and sematonic types
Documentation
//! Projection trait — the core abstraction for ComputeAtom views.
//!
//! Each projection is a deterministic pure function over a byte slice.
//! Projections define their own memory layout (byte_size) and contribute
//! to the atom's shape hash (σ).

/// Unique identifier for a projection type.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub enum ProjectionId {
    Splat,
    Kuramoto,
    Expert,
    Graph,
    Thermal,
}

impl ProjectionId {
    /// Deterministic hash contribution for the projection type itself.
    pub fn type_hash(self) -> u32 {
        match self {
            ProjectionId::Splat => 0x5A1A_0001,
            ProjectionId::Kuramoto => 0x4B55_0002,
            ProjectionId::Expert => 0x3E58_0003,
            ProjectionId::Graph => 0x4752_0004,
            ProjectionId::Thermal => 0x5448_0005,
        }
    }
}

/// A projection is a typed view over a contiguous byte region within a ComputeAtom.
///
/// Implementations must be deterministic: same bytes in → same state out.
/// `byte_size()` is const per type (known at compile time).
pub trait Projection: Sized {
    /// Fixed byte size of this projection's memory region.
    fn byte_size() -> usize;

    /// Projection type identifier.
    fn id() -> ProjectionId;

    /// Read projection state from a byte slice.
    /// Panics if `buf.len() < Self::byte_size()`.
    fn read(buf: &[u8]) -> Self;

    /// Write projection state into a byte slice.
    /// Panics if `buf.len() < Self::byte_size()`.
    fn write(&self, buf: &mut [u8]);

    /// Contribution to the atom's shape hash (FNV-1a input).
    fn shape_hash_contribution(&self) -> u32;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_projection_id_type_hash_unique() {
        let ids = [
            ProjectionId::Splat,
            ProjectionId::Kuramoto,
            ProjectionId::Expert,
            ProjectionId::Graph,
            ProjectionId::Thermal,
        ];
        let hashes: Vec<u32> = ids.iter().map(|id| id.type_hash()).collect();
        for i in 0..hashes.len() {
            for j in (i + 1)..hashes.len() {
                assert_ne!(hashes[i], hashes[j], "Hash collision between {:?} and {:?}", ids[i], ids[j]);
            }
        }
    }
}