vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
//! Flat-byte CPU adapters for hash Category C descriptors.

use crate::ops::hash;
use crate::ops::hash::reference::kdf::Argon2idParams;

pub fn md5(input: &[u8], output: &mut Vec<u8>) {
    extend_u32s(output, &hash::md5::md5(input));
}
pub fn sha1(input: &[u8], output: &mut Vec<u8>) {
    extend_u32s(output, &hash::sha1::sha1(input));
}
pub fn sha256(input: &[u8], output: &mut Vec<u8>) {
    extend_u32s(output, &hash::sha256::sha256(input));
}
pub fn sha384(input: &[u8], output: &mut Vec<u8>) {
    extend_u64s(output, &hash::sha384::sha384(input));
}
pub fn sha512(input: &[u8], output: &mut Vec<u8>) {
    extend_u64s(output, &hash::sha512::sha512(input));
}
pub fn sha3_256(input: &[u8], output: &mut Vec<u8>) {
    extend_u32s(output, &hash::sha3_256::sha3_256(input));
}
pub fn sha3_512(input: &[u8], output: &mut Vec<u8>) {
    extend_u64s(output, &hash::sha3_512::sha3_512(input));
}
pub fn blake2b(input: &[u8], output: &mut Vec<u8>) {
    extend_u64s(output, &hash::blake2b::blake2b(input));
}
pub fn blake2s(input: &[u8], output: &mut Vec<u8>) {
    extend_u32s(output, &hash::blake2s::blake2s(input));
}
pub fn blake3(input: &[u8], output: &mut Vec<u8>) {
    extend_u32s(output, &hash::blake3::blake3(input));
}
pub fn ripemd160(input: &[u8], output: &mut Vec<u8>) {
    extend_u32s(output, &hash::ripemd160::ripemd160(input));
}
pub fn xxhash64(input: &[u8], output: &mut Vec<u8>) {
    output.clear();
    output.extend_from_slice(&hash::xxhash64::xxhash64(input).to_le_bytes());
}
pub fn xxhash3_64(input: &[u8], output: &mut Vec<u8>) {
    output.clear();
    output.extend_from_slice(&hash::xxhash3_64::xxhash3_64(input).to_le_bytes());
}

pub fn hmac_md5(input: &[u8], output: &mut Vec<u8>) {
    let (key, msg) = split_half(input);
    extend_u32s(output, &hash::hmac_md5::hmac_md5(key, msg));
}

pub fn hmac_sha1(input: &[u8], output: &mut Vec<u8>) {
    let (key, msg) = split_half(input);
    extend_u32s(output, &hash::hmac_sha1::hmac_sha1(key, msg));
}

pub fn hmac_sha256(input: &[u8], output: &mut Vec<u8>) {
    let (key, msg) = split_half(input);
    extend_u32s(output, &hash::hmac_sha256::hmac_sha256(key, msg));
}

pub fn hkdf_extract(input: &[u8], output: &mut Vec<u8>) {
    let (salt, ikm) = split_half(input);
    extend_u32s(output, &hash::hkdf_extract::hkdf_extract(salt, ikm));
}

pub fn hkdf_expand(input: &[u8], output: &mut Vec<u8>) {
    let (payload, length) = split_trailing_u32(input);
    let (prk, info) = split_half(payload);
    write_result(output, hash::hkdf_expand::hkdf_expand(prk, info, length));
}

pub fn pbkdf2_sha256(input: &[u8], output: &mut Vec<u8>) {
    let (payload, dk_len) = split_trailing_u32(input);
    let (payload, iterations) = split_trailing_u32(payload);
    let (password, salt) = split_half(payload);
    write_result(
        output,
        hash::pbkdf2_sha256::pbkdf2_sha256(password, salt, iterations, dk_len),
    );
}

pub fn argon2id(input: &[u8], output: &mut Vec<u8>) {
    let (password, salt) = split_half(input);
    let params = Argon2idParams {
        memory_kib: 32,
        iterations: 1,
        parallelism: 1,
        output_len: 32,
    };
    write_result(output, hash::argon2id::argon2id(password, salt, params));
}

pub fn siphash13(input: &[u8], output: &mut Vec<u8>) {
    let (msg, key) = split_trailing_u64(input);
    output.clear();
    output.extend_from_slice(&hash::siphash13::siphash13(msg, key).to_le_bytes());
}

fn extend_u32s(output: &mut Vec<u8>, words: &[u32]) {
    output.clear();
    for word in words {
        output.extend_from_slice(&word.to_le_bytes());
    }
}

fn extend_u64s(output: &mut Vec<u8>, words: &[u64]) {
    output.clear();
    for word in words {
        output.extend_from_slice(&word.to_le_bytes());
    }
}

fn split_half(input: &[u8]) -> (&[u8], &[u8]) {
    input.split_at(input.len() / 2)
}

fn split_trailing_u32(input: &[u8]) -> (&[u8], u32) {
    if input.len() < 4 {
        return (input, 0);
    }
    let split = input.len() - 4;
    let value = u32::from_le_bytes([
        input[split],
        input[split + 1],
        input[split + 2],
        input[split + 3],
    ]);
    (&input[..split], value)
}

fn split_trailing_u64(input: &[u8]) -> (&[u8], u64) {
    if input.len() < 8 {
        return (input, 0);
    }
    let split = input.len() - 8;
    let value = u64::from_le_bytes([
        input[split],
        input[split + 1],
        input[split + 2],
        input[split + 3],
        input[split + 4],
        input[split + 5],
        input[split + 6],
        input[split + 7],
    ]);
    (&input[..split], value)
}

fn write_result(output: &mut Vec<u8>, result: Result<Vec<u8>, String>) {
    output.clear();
    match result {
        Ok(bytes) => output.extend_from_slice(&bytes),
        Err(error) => tracing::error!("{error}. Fix: provide valid hash intrinsic parameters."),
    }
}