hara-native 0.1.13

HAL-free native host runtime and package launcher for Hara
Documentation
use sha2::{Digest, Sha256};

const HLC_MAGIC: &[u8; 4] = b"HLC1";
const HLC_ARTIFACT: &[u8] = include_bytes!("../../assets/language-conformance.hlc");
const ERROR_EXPECTATION_PREFIX: &str = "!error:";

#[derive(Debug)]
struct HlcCase<'a> {
    id: &'a str,
    layer: &'a str,
    expected: HlcExpectation<'a>,
    browser_safe: bool,
    source: &'a str,
    artifact: &'a [u8],
}

#[derive(Debug, Clone, Copy)]
enum HlcExpectation<'a> {
    Display(&'a str),
    Error(&'a str),
}

impl<'a> HlcExpectation<'a> {
    fn parse(value: &'a str) -> Self {
        match value.strip_prefix(ERROR_EXPECTATION_PREFIX) {
            Some(category) => Self::Error(category),
            None => Self::Display(value),
        }
    }
}

struct HlcReader<'a> {
    bytes: &'a [u8],
    offset: usize,
}

impl<'a> HlcReader<'a> {
    fn new(bytes: &'a [u8]) -> Self {
        Self { bytes, offset: 0 }
    }

    fn u32(&mut self) -> Result<usize, String> {
        Ok(u32::from_le_bytes(self.take(4)?.try_into().expect("four bytes")) as usize)
    }

    fn boolean(&mut self) -> Result<bool, String> {
        match self.u32()? {
            0 => Ok(false),
            1 => Ok(true),
            _ => Err("HLC1 boolean field must be zero or one".into()),
        }
    }

    fn bytes(&mut self) -> Result<&'a [u8], String> {
        let length = self.u32()?;
        self.take(length)
    }

    fn text(&mut self, field: &str) -> Result<&'a str, String> {
        std::str::from_utf8(self.bytes()?).map_err(|_| format!("HLC1 {field} is not UTF-8"))
    }

    fn take(&mut self, length: usize) -> Result<&'a [u8], String> {
        let end = self
            .offset
            .checked_add(length)
            .ok_or_else(|| "HLC1 field length overflows the artifact".to_owned())?;
        let value = self
            .bytes
            .get(self.offset..end)
            .ok_or_else(|| "HLC1 field exceeds the artifact".to_owned())?;
        self.offset = end;
        Ok(value)
    }

    fn finish(&self) -> Result<(), String> {
        if self.offset == self.bytes.len() {
            Ok(())
        } else {
            Err("HLC1 artifact has trailing bytes".into())
        }
    }
}

fn parse_hlc(bytes: &[u8]) -> Result<Vec<HlcCase<'_>>, String> {
    if !bytes.starts_with(HLC_MAGIC) || bytes.len() < 36 {
        return Err("HLC1 artifact has an invalid or truncated header".into());
    }
    let (digest, payload) = bytes[4..].split_at(32);
    let expected: [u8; 32] = digest.try_into().expect("HLC1 digest has 32 bytes");
    let actual: [u8; 32] = Sha256::digest(payload).into();
    if actual != expected {
        return Err("HLC1 artifact checksum mismatch".into());
    }
    let mut reader = HlcReader::new(payload);
    let count = reader.u32()?;
    if count == 0 || count > reader.bytes.len() / 24 {
        return Err("HLC1 has an invalid case count".into());
    }
    let mut cases = Vec::with_capacity(count);
    for _ in 0..count {
        let id = reader.text("case id")?;
        let layer = reader.text("case layer")?;
        if !matches!(layer, "parser" | "evaluator" | "native-abi") {
            return Err(format!("HLC1 {id} has an invalid layer {layer:?}"));
        }
        let expected = HlcExpectation::parse(reader.text("case expectation")?);
        let browser_safe = reader.boolean()?;
        let source = reader.text("case source")?;
        let artifact = reader.bytes()?;
        cases.push(HlcCase {
            id,
            layer,
            expected,
            browser_safe,
            source,
            artifact,
        });
    }
    reader.finish()?;
    Ok(cases)
}

fn requires_source_library(program: &crate::vm::Program) -> bool {
    program.constants.iter().any(|value| {
        let text = value.display();
        text.starts_with("std.foundation/")
            || text.starts_with("std.foundation.")
            || text.starts_with("std.lib/")
            || text.starts_with("std.lib.")
    })
}

fn normalized_error_category(error: &str) -> Option<&'static str> {
    let error = error.trim_start_matches("error: ");
    if error.contains("division by zero") {
        Some("division by zero")
    } else if error.contains("expects numbers") {
        Some("expects numbers")
    } else {
        None
    }
}

fn assert_outcome(case: &HlcCase<'_>, actual: Result<String, String>) -> Result<(), String> {
    match (case.expected, actual) {
        (HlcExpectation::Display(expected), Ok(actual)) if actual == expected => Ok(()),
        (HlcExpectation::Display(expected), Ok(actual)) => Err(format!(
            "{} ({}) expected display {expected:?}, observed {actual:?}",
            case.id, case.layer
        )),
        (HlcExpectation::Display(expected), Err(error)) => Err(format!(
            "{} ({}) expected display {expected:?}, raised {error}",
            case.id, case.layer
        )),
        (HlcExpectation::Error(expected), Err(error))
            if normalized_error_category(&error) == Some(expected) =>
        {
            Ok(())
        }
        (HlcExpectation::Error(expected), Err(error)) => Err(format!(
            "{} ({}) expected error {expected:?}, observed {error:?} ({:?})",
            case.id,
            case.layer,
            normalized_error_category(&error)
        )),
        (HlcExpectation::Error(expected), Ok(actual)) => Err(format!(
            "{} ({}) expected error {expected:?}, returned {actual:?}",
            case.id, case.layer
        )),
    }
}

#[test]
fn core_runtime_executes_every_hlc1_case_from_rust_produced_hbc0() {
    let cases = parse_hlc(HLC_ARTIFACT).expect("embedded HLC1 corpus is valid");
    assert!(
        cases.len() >= 20,
        "HLC1 corpus must cover functional behavior"
    );
    assert!(cases.iter().any(|case| case.layer == "parser"));
    assert!(cases.iter().any(|case| case.layer == "evaluator"));
    assert!(cases.iter().any(|case| case.layer == "native-abi"));
    assert!(cases.iter().any(|case| case.browser_safe));

    for case in &cases {
        let program = crate::vm::decode_program(case.artifact)
            .unwrap_or_else(|error| panic!("{} has invalid HBC0: {error}", case.id));
        assert_eq!(
            crate::vm::encode_program(&program).unwrap(),
            case.artifact,
            "{} HBC0 must be canonical",
            case.id
        );
        assert!(
            !requires_source_library(&program),
            "{} must not require a source package",
            case.id
        );
        let source_actual = crate::Runtime::core().eval_native(case.source);
        assert_outcome(case, source_actual)
            .unwrap_or_else(|error| panic!("source conformance failure: {error}"));
        let artifact_actual = crate::Runtime::core().eval_bytecode_artifact(case.artifact);
        assert_outcome(case, artifact_actual)
            .unwrap_or_else(|error| panic!("artifact conformance failure: {error}"));
    }
}

#[test]
fn hlc1_rejects_corruption_and_wrong_normalized_errors() {
    let mut corrupted = HLC_ARTIFACT.to_vec();
    corrupted[36] ^= 1;
    assert!(parse_hlc(&corrupted).unwrap_err().contains("checksum"));
    let wrong = HlcCase {
        id: "fixture/error",
        layer: "evaluator",
        expected: HlcExpectation::Error("division by zero"),
        browser_safe: false,
        source: "(/ 1 0)",
        artifact: &[],
    };
    assert!(assert_outcome(&wrong, Err("expects numbers".into())).is_err());
}