vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
use crate::ir::DataType;
use crate::ops::Backend;
use crate::ops::{IntrinsicDescriptor, OpSpec};

// WGSL lowering source for `hash.hmac_sha256`.

/// Shared WGSL helpers used by the HMAC-SHA-256 lowering.
pub const WGSL: &str = concat!(
    include_str!("wgsl_shaders/words.wgsl"),
    "\n",
    include_str!("wgsl_shaders/sha256.wgsl"),
);

pub const BLOCK_BYTES: usize = 64;

/// Compute HMAC-SHA-256 and return eight big-endian digest words.
#[must_use]
pub fn hmac_sha256(key: &[u8], msg: &[u8]) -> [u32; 8] {
    let mut key_block = [0u8; BLOCK_BYTES];
    if key.len() > BLOCK_BYTES {
        let key_hash = crate::ops::hash::reference::sha256::sha256_words(key);
        for (chunk, word) in key_block.chunks_exact_mut(4).zip(key_hash) {
            chunk.copy_from_slice(&word.to_be_bytes());
        }
    } else {
        key_block[..key.len()].copy_from_slice(key);
    }

    let mut inner = Vec::with_capacity(BLOCK_BYTES + msg.len());
    inner.extend(key_block.iter().map(|byte| byte ^ 0x36));
    inner.extend_from_slice(msg);
    let inner_hash = crate::ops::hash::reference::sha256::sha256_words(&inner);

    let mut outer = Vec::with_capacity(BLOCK_BYTES + 32);
    outer.extend(key_block.iter().map(|byte| byte ^ 0x5c));
    for word in inner_hash {
        outer.extend_from_slice(&word.to_be_bytes());
    }
    crate::ops::hash::reference::sha256::sha256_words(&outer)
}

pub const INPUTS: &[DataType] = &[DataType::Bytes, DataType::Bytes];

pub const LAWS: &[crate::ops::AlgebraicLaw] = &[];

pub const OUTPUTS: &[DataType] = &[const { DataType::U32 }; 8];

/// Declarative operation specification for `hash.hmac_sha256`.
pub const SPEC: OpSpec = OpSpec::intrinsic(
    "hash.hmac_sha256",
    INPUTS,
    OUTPUTS,
    LAWS,
    wgsl_only,
    IntrinsicDescriptor::new(
        "hash.hmac_sha256.wgsl",
        "wgsl-hmac-sha256",
        crate::ops::hash::cpu_refs::hmac_sha256,
    ),
);

pub fn wgsl_only(backend: &Backend) -> bool {
    matches!(backend, Backend::Wgsl)
}