baryl 0.0.2

Public SDK for Baryl, a full-system emulation and introspection engine
//! The two hashes that turn a name into a number at compile time.
//!
//! [`vmcall_enum!`](crate::vmcall_enum) builds its discriminants out of the
//! 32-bit one and [`tag_enum!`](crate::tag_enum) out of the 64-bit one. Call
//! them directly when you need the same number on the other side of a boundary
//! the macros do not cross — a C component, or a guest agent computing the
//! vmcall it is about to make.

/// FNV-1a over `s`, 32 bits, evaluated at compile time.
///
/// This is the number `vmcall_enum!` gives a variant, so a guest agent or a C
/// component can spell the same discriminant from the same name.
///
/// # Examples
///
/// ```ignore
/// const READY: u32 = fnv1a_32("Ready");
/// assert_eq!(READY, 0x0bca_3294);
/// ```
#[must_use]
pub const fn fnv1a_32(s: &str) -> u32 {
    let bytes = s.as_bytes();
    let mut hash: u32 = 0x811c_9dc5;
    let mut i = 0;
    while i < bytes.len() {
        hash ^= bytes[i] as u32;
        hash = hash.wrapping_mul(0x0100_0193);
        i += 1;
    }
    hash
}

/// FNV-1a over `s`, 64 bits, evaluated at compile time.
///
/// `tag_enum!` hashes `"EnumName::VariantName"` with this, so the same string
/// here reproduces a tag by hand.
///
/// # Examples
///
/// ```ignore
/// const WRITE_FILE: u64 = fnv1a_64("CmdTag::WriteFile");
/// assert_eq!(WRITE_FILE, 0x0e3a_03f3_7c93_bb56);
/// ```
#[must_use]
pub const fn fnv1a_64(s: &str) -> u64 {
    let bytes = s.as_bytes();
    let mut hash: u64 = 0xcbf29ce484222325;
    let mut i = 0;
    while i < bytes.len() {
        hash ^= bytes[i] as u64;
        hash = hash.wrapping_mul(0x00000100000001B3);
        i += 1;
    }
    hash
}