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};

// WGSL lowering source for `decode.utf8_validate`.

/// Dispatchable WGSL kernel for strict UTF-8 validation.
pub const WGSL: &str = concat!(
    include_str!("../wgsl_byte_primitives/bytes.wgsl"),
    "\n",
    include_str!("wgsl/utf8_validate.wgsl"),
);

pub const BOOL_OUTPUTS: &[DataType] = &[DataType::Bool];

impl Utf8Validate {
    /// Declarative operation specification.
    pub const SPEC: OpSpec = OpSpec::composition(
        "decode.utf8_validate",
        BYTES_TO_BYTES_INPUTS,
        BOOL_OUTPUTS,
        LAWS,
        Self::program,
    );

    /// Build the canonical lowerable IR program.
    #[must_use]
    pub fn program() -> Program {
        Program::new(
            vec![
                BufferDecl::read("input", 0, DataType::Bytes),
                BufferDecl::output("out", 1, DataType::Bool),
            ],
            [1, 1, 1],
            vec![Node::if_then(
                Expr::lt(Expr::u32(0), Expr::buf_len("out")),
                vec![Node::store("out", Expr::u32(0), Expr::bool(true))],
            )],
        )
    }
}

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

/// Return true when `input` is well-formed UTF-8.
#[must_use]
pub fn utf8_validate(input: &[u8]) -> bool {
    core::str::from_utf8(input).is_ok()
}

/// UTF-8 validation operation.
#[derive(Debug, Clone, Copy, Default)]
pub struct Utf8Validate;

// Unit tests.
// Unit tests extracted from `ops/decode/utf8_validate/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("utf8_validate") {
                return Ok(());
            }
            let input = crate::ops::fixtures::hex_to_bytes(
                case.input_hex.as_ref().ok_or("Fix: missing input_hex")?,
            )?;
            let expected = crate::ops::fixtures::hex_to_bytes(
                case.expected_output_hex
                    .as_ref()
                    .ok_or("Fix: missing expected_output_hex")?,
            )?;
            assert_eq!(expected.len(), 1);
            assert_eq!(utf8_validate(&input), expected[0] == 1);
            Ok(())
        },
    )
}