#![cfg(feature = "vyre-foundation")]
use vyre_foundation::ir::{DataType, Expr};
#[must_use]
pub fn byte_table_lookup(table: &str, byte: Expr) -> Expr {
Expr::load(table, Expr::bitand(byte, Expr::u32(0xFF)))
}
#[must_use]
pub fn source_byte_table_lookup(table: &str, source: &str, index: Expr) -> Expr {
byte_table_lookup(table, Expr::cast(DataType::U32, Expr::load(source, index)))
}
#[must_use]
pub fn clamped_load(buf: &str, idx: Expr) -> Expr {
clamped_load_to(buf, idx, Expr::buf_len(buf))
}
#[must_use]
pub fn clamped_load_to(buf: &str, idx: Expr, bound: Expr) -> Expr {
let safe_idx = Expr::select(
Expr::lt(idx.clone(), bound.clone()),
idx,
Expr::saturating_sub(bound, Expr::u32(1)),
);
Expr::load(buf, safe_idx)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn byte_table_lookup_masks_the_index() {
let expr = byte_table_lookup("table", Expr::u32(0x0141));
let rendered = format!("{expr:?}");
assert!(
rendered.contains("255") || rendered.contains("0xFF") || rendered.contains("Ff"),
"byte_table_lookup must AND the index with 0xFF; got {rendered}"
);
}
#[test]
fn clamped_load_bounds_the_index_against_buf_len() {
let expr = clamped_load("buf", Expr::u32(9_999));
let rendered = format!("{expr:?}");
assert!(
rendered.contains("BufLen") || rendered.contains("buf_len"),
"clamped_load must clamp against the buffer length; got {rendered}"
);
}
#[test]
fn clamped_load_to_clamps_against_the_caller_bound_not_buf_len() {
let expr = clamped_load_to("buf", Expr::u32(9_999), Expr::u32(7));
let rendered = format!("{expr:?}");
assert!(
!rendered.contains("BufLen"),
"clamped_load_to must clamp against the caller bound, not BufLen; got {rendered}"
);
assert!(
rendered.contains('7') || rendered.contains("Select"),
"clamped_load_to must select the safe index against the given bound; got {rendered}"
);
}
}