vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
use super::numeric_prefix::{read_u32_prefix, read_u64_prefix};
use super::value_enum::Value;

impl Value {
    /// Try to interpret the value as the IR's scalar `u32` word.
    #[must_use]
    #[inline]
    pub fn try_as_u32(&self) -> Option<u32> {
        match self {
            Self::U32(v) => Some(*v),
            Self::I32(v) => u32::try_from(*v).ok(),
            Self::U64(v) => u32::try_from(*v).ok(),
            Self::Bool(v) => Some(u32::from(*v)),
            Self::Bytes(bytes) => (bytes.len() <= 4).then(|| read_u32_prefix(bytes)),
            Self::Float(v) => Some(*v as u32),
            Self::Tensor(_) | Self::Array(_) => None,
        }
    }

    /// Interpret the value as the IR's scalar `u32` word.
    #[inline]
    pub fn as_u32(&self) -> u32 {
        self.try_as_u32().unwrap_or_else(|| {
            panic!(
                "Value cannot be represented losslessly as u32: {self:?}. \
                 Fix: call try_as_u32 and handle the None case."
            )
        })
    }

    /// Try to interpret the value as a full `u64`.
    #[must_use]
    #[inline]
    pub fn try_as_u64(&self) -> Option<u64> {
        match self {
            Self::U32(v) => Some(u64::from(*v)),
            Self::I32(v) => u64::try_from(*v).ok(),
            Self::U64(v) => Some(*v),
            Self::Bool(v) => Some(u64::from(*v)),
            Self::Bytes(bytes) => (bytes.len() <= 8).then(|| read_u64_prefix(bytes)),
            Self::Float(v) => Some(*v as u64),
            Self::Tensor(_) | Self::Array(_) => None,
        }
    }

    /// Interpret the value as a full `u64`. `U32`/`I32` widen
    /// zero-extended, `Bool` widens to 0/1, and `Bytes` decodes the
    /// leading 8 bytes as little-endian. Used by reference-interpreter
    /// casts that must preserve the upper half of a 64-bit payload
    /// (Kimi audit finding #3).
    #[inline]
    pub fn as_u64(&self) -> u64 {
        self.try_as_u64().unwrap_or_else(|| {
            panic!(
                "Value cannot be represented losslessly as u64: {self:?}. \
                 Fix: call try_as_u64 and handle the None case."
            )
        })
    }

    /// Return the full value payload as little-endian bytes, identical
    /// to [`to_bytes`] except named for callers that need the widest
    /// possible byte view (cast targets, multi-word vector casts).
    ///
    /// [`to_bytes`]: Self::to_bytes
    #[inline]
    pub fn wide_bytes(&self) -> Vec<u8> {
        self.to_bytes()
    }
}