axicor-core 0.1.0

Axicor SNN engine — C-ABI memory contracts, SoA layouts, and IPC primitives
Documentation
use std::fs;
use std::path::PathBuf;

/// Root configuration describing the whole brain (multi-zone setup).
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct BrainConfig {
    #[serde(default)]
    pub depart_id_v1: Option<crate::config::sys::SystemMeta>,

    #[serde(default)]
    pub simulation: SimulationConfigRef,

    #[serde(rename = "zone", default)]
    pub zones: Vec<ZoneEntry>,

    #[serde(rename = "connection", default)]
    pub connections: Vec<ConnectionEntry>,
}

use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize, Default, Clone)]
pub struct SimulationConfigRef {
    pub config: PathBuf,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ZoneEntry {
    #[serde(default)]
    pub shard_id_v1: Option<crate::config::sys::SystemMeta>,
    pub name: String,
    pub blueprints: PathBuf,
    pub anatomy: PathBuf,
    pub io: PathBuf,
    pub baked_dir: PathBuf,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ConnectionEntry {
    #[serde(default)]
    pub conn_id_v1: Option<crate::config::sys::SystemMeta>,
    pub from: String,
    pub to: String,
    pub output_matrix: Option<String>,
    pub entry_z: Option<String>,
    pub target_type: Option<String>,
    pub growth_steps: Option<u32>,
    // TODO: In the future, this will contain a path to a connectome file (e.g. `baked/connections/v1_v2.ghosts`),
    // containing millions of connections. For MVP, we use a nested array.
    #[serde(default)]
    pub axon_ids: Vec<u32>,
    pub width: Option<u16>,
    pub height: Option<u16>,
}

/// Parses the `brain.toml` manifest file.
pub fn parse_brain_config(path: &std::path::Path) -> Result<BrainConfig, String> {
    let content = fs::read_to_string(path)
        .map_err(|e| format!("Failed to read brain config file at {:?}: {}", path, e))?;

    parse_brain_config_from_str(&content)
}

pub fn parse_brain_config_from_str(content: &str) -> Result<BrainConfig, String> {
    let config: BrainConfig = toml::from_str(content)
        .map_err(|e| format!("Failed to parse brain config from string: {}", e))?;

    // [DOD FIX] Strict Zone Name Uniqueness
    let mut seen = std::collections::HashSet::new();
    for zone in &config.zones {
        if !seen.insert(&zone.name) {
            return Err(format!("CRITICAL INVARIANT BROKEN: Duplicate zone name found: '{}'", zone.name));
        }
    }

    Ok(config)
}

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

    #[test]
    fn test_parse_brain_config() {
        let toml_str = r#"
        [simulation]
        config = "config/simulation.toml"

        [[zone]]
        name = "V1"
        blueprints = "config/zones/V1/blueprints.toml"
        anatomy = "config/zones/V1/anatomy.toml"
        io = "config/zones/V1/io.toml"
        baked_dir = "baked/V1/"

        [[zone]]
        name = "V2"
        blueprints = "config/zones/V2/blueprints.toml"
        anatomy = "config/zones/V2/anatomy.toml"
        io = "config/zones/V2/io.toml"
        baked_dir = "baked/V2/"

        [[connection]]
        from = "V1"
        to = "V2"
        axon_ids = [100, 101, 102]
        "#;

        let config: BrainConfig = toml::from_str(toml_str).unwrap();
        assert_eq!(
            config.simulation.config.to_str().unwrap(),
            "config/simulation.toml"
        );
        assert_eq!(config.zones.len(), 2);

        assert_eq!(config.zones[0].name, "V1");
        assert_eq!(
            config.zones[0].blueprints.to_str().unwrap(),
            "config/zones/V1/blueprints.toml"
        );
        assert_eq!(
            config.zones[0].anatomy.to_str().unwrap(),
            "config/zones/V1/anatomy.toml"
        );
        assert_eq!(
            config.zones[0].io.to_str().unwrap(),
            "config/zones/V1/io.toml"
        );
        assert_eq!(config.zones[0].baked_dir.to_str().unwrap(), "baked/V1/");

        assert_eq!(config.zones[1].name, "V2");
        assert_eq!(
            config.zones[1].blueprints.to_str().unwrap(),
            "config/zones/V2/blueprints.toml"
        );
        assert_eq!(
            config.zones[1].anatomy.to_str().unwrap(),
            "config/zones/V2/anatomy.toml"
        );
        assert_eq!(
            config.zones[1].io.to_str().unwrap(),
            "config/zones/V2/io.toml"
        );
        assert_eq!(config.zones[1].baked_dir.to_str().unwrap(), "baked/V2/");

        assert_eq!(config.connections.len(), 1);
        assert_eq!(config.connections[0].from, "V1");
        assert_eq!(config.connections[0].to, "V2");
        assert_eq!(config.connections[0].axon_ids, vec![100, 101, 102]);
    }
}