vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
//! Shared IR helpers for byte decoders.

use crate::ir::{BinOp, Expr};
use crate::ops::AlgebraicLaw;

/// Output bytes are bounded to one byte per decoded scalar.
pub const BYTE_BOUNDED_LAWS: &[AlgebraicLaw] = &[AlgebraicLaw::Bounded { lo: 0, hi: 255 }];

/// Build a logical `and` expression.
#[must_use]
pub fn and(left: Expr, right: Expr) -> Expr {
    Expr::BinOp {
        op: BinOp::And,
        left: Box::new(left),
        right: Box::new(right),
    }
}

/// Build a less-than-or-equal expression.
#[must_use]
pub fn le(left: Expr, right: Expr) -> Expr {
    Expr::BinOp {
        op: BinOp::Le,
        left: Box::new(left),
        right: Box::new(right),
    }
}

/// Return whether `value` falls within the inclusive ASCII byte range.
#[must_use]
pub fn in_range(value: Expr, low: u8, high: u8) -> Expr {
    and(
        le(Expr::u32(u32::from(low)), value.clone()),
        le(value, Expr::u32(u32::from(high))),
    )
}

/// Decode one ASCII hex nibble, returning zero for non-hex input.
#[must_use]
pub fn hex_nibble(byte: Expr) -> Expr {
    Expr::select(
        in_range(byte.clone(), b'0', b'9'),
        Expr::sub(byte.clone(), Expr::u32(u32::from(b'0'))),
        Expr::select(
            in_range(byte.clone(), b'A', b'F'),
            Expr::add(
                Expr::sub(byte.clone(), Expr::u32(u32::from(b'A'))),
                Expr::u32(10),
            ),
            Expr::select(
                in_range(byte.clone(), b'a', b'f'),
                Expr::add(Expr::sub(byte, Expr::u32(u32::from(b'a'))), Expr::u32(10)),
                Expr::u32(0),
            ),
        ),
    )
}