vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
//! Program encoder for the stable IR wire format.

use super::put_nodes;
use crate::ir::serial::wire::framing::{
    put_len_u32, put_string, put_u32, put_u8, MAGIC, WIRE_FORMAT_VERSION,
};
use crate::ir::serial::wire::tags::{access_tag, put_data_type};
use crate::ir::serial::wire::Program;

/// Serialize a complete program into the `VIR0` wire envelope.
///
/// # Errors
///
/// Returns an actionable error if a program field exceeds the wire-format
/// bounds or contains an enum variant without a stable tag.
#[inline]
pub fn to_wire(program: &Program) -> Result<Vec<u8>, String> {
    // Heuristic upper bound: MAGIC + entry_op_id tag + rough per-buffer
    // and per-node estimate. Saves one or two reallocations on typical
    // programs; still grows naturally for larger inputs.
    let capacity = MAGIC.len()
        + 1
        + program.entry_op_id().map_or(0, |id| 4 + id.len())
        + 4
        + program.buffers().len() * 32
        + 12
        + 4
        + program.entry().len() * 16;
    let mut out = Vec::with_capacity(capacity + 2);
    out.extend_from_slice(MAGIC);
    // L.1.47: emit the wire-format schema version right after the
    // magic so older decoders recognise a newer payload and reject
    // with an actionable message instead of producing arbitrary
    // downstream tag/length errors.
    out.extend_from_slice(&WIRE_FORMAT_VERSION.to_le_bytes());
    match program.entry_op_id() {
        Some(op_id) => {
            put_u8(&mut out, 1);
            put_string(&mut out, op_id)?;
        }
        None => put_u8(&mut out, 0),
    }
    put_len_u32(&mut out, program.buffers().len(), "buffer count")?;
    for buffer in program.buffers() {
        put_string(&mut out, &buffer.name)?;
        put_u32(&mut out, buffer.binding);
        put_u8(&mut out, access_tag(buffer.access.clone())?);
        put_data_type(&mut out, &buffer.element)?;
        put_u32(&mut out, buffer.count);
        put_u8(&mut out, u8::from(buffer.is_output));
    }
    for size in program.workgroup_size {
        put_u32(&mut out, size);
    }
    put_nodes(&mut out, program.entry())?;
    Ok(out)
}