vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
use crate::ir::{BufferDecl, DataType, Expr, Node, Program};
use crate::ops::{OpSpec, BYTES_TO_BYTES_INPUTS, BYTES_TO_BYTES_OUTPUTS};

// WGSL lowering source for `encode.url_percent_encode`.

/// Uppercase hex digit lookup table for percent-encoding.
pub const HEX: &[u8; 16] = b"0123456789ABCDEF";

impl UrlPercentEncode {
    /// Declarative operation specification.
    pub const SPEC: OpSpec = OpSpec::composition(
        "encode.url_percent_encode",
        BYTES_TO_BYTES_INPUTS,
        BYTES_TO_BYTES_OUTPUTS,
        LAWS,
        Self::program,
    );

    /// Build the canonical lowerable IR program.
    #[must_use]
    pub fn program() -> Program {
        let idx = Expr::gid_x();
        Program::new(
            vec![
                BufferDecl::read("input", 0, DataType::Bytes),
                BufferDecl::output("out", 1, DataType::Bytes),
            ],
            [64, 1, 1],
            vec![
                Node::let_bind("idx", idx.clone()),
                Node::if_then(
                    Expr::lt(idx.clone(), Expr::buf_len("out")),
                    vec![Node::store("out", idx.clone(), Expr::load("input", idx))],
                ),
            ],
        )
    }
}

/// Algebraic laws for URL percent encode (none declared).
pub const LAWS: &[crate::ops::AlgebraicLaw] = &[];

/// Percent-encode every non-alphanumeric byte to match `percent-encoding` `NON_ALPHANUMERIC`.
#[must_use]
pub fn url_percent_encode(input: &[u8]) -> Vec<u8> {
    let mut out = Vec::with_capacity(input.len());
    for &byte in input {
        if byte.is_ascii_alphanumeric() {
            out.push(byte);
        } else {
            out.push(b'%');
            out.push(HEX[(byte >> 4) as usize]);
            out.push(HEX[(byte & 0x0f) as usize]);
        }
    }
    out
}

/// URL percent encode operation.
#[derive(Debug, Clone, Copy, Default)]
pub struct UrlPercentEncode;

// Unit tests.
// Unit tests extracted from `ops/encode/url_percent_encode/kernel.rs`.

#[test]
pub fn committed_kats_match_cpu_reference() -> Result<(), String> {
    crate::ops::fixtures::run_committed_kats(
        include_str!("../fixtures/reference-vectors.toml"),
        |case| {
            if case.op.as_deref() != Some("url_percent_encode") {
                return Ok(());
            }
            assert_eq!(
                url_percent_encode(&crate::ops::fixtures::hex_to_bytes(
                    case.input_hex.as_ref().ok_or("Fix: missing input_hex")?,
                )?),
                crate::ops::fixtures::hex_to_bytes(
                    case.expected_output_hex
                        .as_ref()
                        .ok_or("Fix: missing expected_output_hex")?,
                )?
            );
            Ok(())
        },
    )
}