vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
struct Base64UrlParams {
    input_len: u32,
    output_capacity: u32,
    reserved0: u32,
    reserved1: u32,
}

@group(0) @binding(0) var<uniform> params: Base64UrlParams;
@group(0) @binding(1) var<storage, read> input_words: array<u32>;
@group(0) @binding(2) var<storage, read_write> output_words: array<u32>;
@group(0) @binding(3) var<storage, read_write> status: array<u32>;

fn decode_base64url_value(byte: u32) -> u32 {
    if (byte >= 65u && byte <= 90u) { return byte - 65u; }
    if (byte >= 97u && byte <= 122u) { return byte - 71u; }
    if (byte >= 48u && byte <= 57u) { return byte + 4u; }
    if (byte == 45u) { return 62u; }
    if (byte == 95u) { return 63u; }
    return 0xffffffffu;
}

@compute @workgroup_size(1, 1, 1)
fn decode_base64url(@builtin(global_invocation_id) id: vec3<u32>) {
    if (id.x != 0u) {
        return;
    }
    status[0] = 0u;
    status[1] = 0u;
    var data_len = params.input_len;
    var first_pad = params.input_len;
    var scan = 0u;
    loop {
        if (scan >= params.input_len) { break; }
        if (vyre_packed_byte(&input_words, scan) == 61u) {
            first_pad = scan;
            data_len = scan;
            break;
        }
        scan = scan + 1u;
    }
    if (first_pad < params.input_len) {
        var pad = first_pad;
        loop {
            if (pad >= params.input_len) { break; }
            if (vyre_packed_byte(&input_words, pad) != 61u) {
                status[0] = 3u;
                status[1] = pad;
                return;
            }
            pad = pad + 1u;
        }
        if ((params.input_len & 3u) != 0u) {
            status[0] = 3u;
            status[1] = first_pad;
            return;
        }
    }
    if ((data_len & 3u) == 1u) {
        status[0] = 1u;
        return;
    }
    var buffer = 0u;
    var bits = 0u;
    var out = 0u;
    var input = 0u;
    loop {
        if (input >= data_len) { break; }
        let value = decode_base64url_value(vyre_packed_byte(&input_words, input));
        if (value == 0xffffffffu) {
            status[0] = 2u;
            status[1] = input;
            return;
        }
        buffer = (buffer << 6u) | value;
        bits = bits + 6u;
        if (bits >= 8u) {
            if (out >= params.output_capacity) {
                status[0] = 5u;
                return;
            }
            bits = bits - 8u;
            vyre_store_packed_byte(&output_words, out, (buffer >> bits) & 0xffu);
            out = out + 1u;
        }
        input = input + 1u;
    }
    status[1] = out;
}