use xxhash_rust::xxh3::xxh3_64;
pub const REDEX_ENTRY_SIZE: usize = 20;
pub const INLINE_PAYLOAD_SIZE: usize = 8;
pub struct RedexFlags;
impl RedexFlags {
pub const INLINE: u32 = 0x8000_0000;
pub const TOMBSTONE: u32 = 0x4000_0000;
pub const COMPACTED: u32 = 0x2000_0000;
}
const FLAG_MASK: u32 = 0xF000_0000;
const CHECKSUM_MASK: u32 = 0x0FFF_FFFF;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RedexEntry {
pub seq: u64,
pub payload_offset: u32,
pub payload_len: u32,
pub flags_and_checksum: u32,
}
impl RedexEntry {
pub fn new_heap(seq: u64, offset: u32, len: u32, flags: u32, checksum: u32) -> Self {
assert!(
flags & RedexFlags::INLINE == 0,
"new_heap rejects flags=INLINE; use new_inline for inline payloads"
);
Self {
seq,
payload_offset: offset,
payload_len: len,
flags_and_checksum: (flags & FLAG_MASK) | (checksum & CHECKSUM_MASK),
}
}
#[expect(
clippy::expect_used,
reason = "input is &[u8; INLINE_PAYLOAD_SIZE]; fixed slice converts are statically infallible"
)]
pub fn new_inline(seq: u64, payload: &[u8; INLINE_PAYLOAD_SIZE], checksum: u32) -> Self {
let offset = u32::from_le_bytes(payload[0..4].try_into().expect("4 bytes"));
let len = u32::from_le_bytes(payload[4..8].try_into().expect("4 bytes"));
Self {
seq,
payload_offset: offset,
payload_len: len,
flags_and_checksum: RedexFlags::INLINE | (checksum & CHECKSUM_MASK),
}
}
#[inline]
pub fn is_inline(&self) -> bool {
self.flags_and_checksum & RedexFlags::INLINE != 0
}
#[inline]
pub fn flags(&self) -> u32 {
self.flags_and_checksum & FLAG_MASK
}
#[inline]
pub fn checksum(&self) -> u32 {
self.flags_and_checksum & CHECKSUM_MASK
}
pub fn inline_payload(&self) -> Option<[u8; INLINE_PAYLOAD_SIZE]> {
if !self.is_inline() {
return None;
}
let mut out = [0u8; INLINE_PAYLOAD_SIZE];
out[0..4].copy_from_slice(&self.payload_offset.to_le_bytes());
out[4..8].copy_from_slice(&self.payload_len.to_le_bytes());
Some(out)
}
#[inline(always)]
pub fn to_bytes(&self) -> [u8; REDEX_ENTRY_SIZE] {
let mut out = [0u8; REDEX_ENTRY_SIZE];
out[0..8].copy_from_slice(&self.seq.to_le_bytes());
out[8..12].copy_from_slice(&self.payload_offset.to_le_bytes());
out[12..16].copy_from_slice(&self.payload_len.to_le_bytes());
out[16..20].copy_from_slice(&self.flags_and_checksum.to_le_bytes());
out
}
#[expect(
clippy::expect_used,
reason = "input is &[u8; REDEX_ENTRY_SIZE]; fixed slice converts are statically infallible"
)]
#[inline(always)]
pub fn from_bytes(bytes: &[u8; REDEX_ENTRY_SIZE]) -> Self {
Self {
seq: u64::from_le_bytes(bytes[0..8].try_into().expect("8 bytes")),
payload_offset: u32::from_le_bytes(bytes[8..12].try_into().expect("4 bytes")),
payload_len: u32::from_le_bytes(bytes[12..16].try_into().expect("4 bytes")),
flags_and_checksum: u32::from_le_bytes(bytes[16..20].try_into().expect("4 bytes")),
}
}
}
#[inline]
pub fn payload_checksum(payload: &[u8]) -> u32 {
(xxh3_64(payload) as u32) & CHECKSUM_MASK
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_entry_size() {
assert_eq!(REDEX_ENTRY_SIZE, 20);
}
#[test]
fn test_heap_roundtrip() {
let e = RedexEntry::new_heap(42, 1024, 256, 0, 0x0123_4567);
let bytes = e.to_bytes();
assert_eq!(bytes.len(), 20);
let decoded = RedexEntry::from_bytes(&bytes);
assert_eq!(e, decoded);
assert!(!decoded.is_inline());
assert_eq!(decoded.payload_offset, 1024);
assert_eq!(decoded.payload_len, 256);
assert_eq!(decoded.checksum(), 0x0123_4567);
}
#[test]
fn test_inline_roundtrip() {
let payload: [u8; 8] = *b"abcd1234";
let cks = payload_checksum(&payload);
let e = RedexEntry::new_inline(7, &payload, cks);
let bytes = e.to_bytes();
let decoded = RedexEntry::from_bytes(&bytes);
assert_eq!(e, decoded);
assert!(decoded.is_inline());
assert_eq!(decoded.inline_payload().unwrap(), payload);
}
#[test]
fn test_inline_zeros() {
let payload = [0u8; 8];
let e = RedexEntry::new_inline(0, &payload, 0);
let decoded = RedexEntry::from_bytes(&e.to_bytes());
assert!(decoded.is_inline());
assert_eq!(decoded.inline_payload().unwrap(), payload);
}
#[test]
fn test_inline_all_high_bits() {
let payload = [0xFFu8; 8];
let e = RedexEntry::new_inline(3, &payload, 0);
let decoded = RedexEntry::from_bytes(&e.to_bytes());
assert!(decoded.is_inline());
assert_eq!(decoded.inline_payload().unwrap(), payload);
}
#[test]
fn test_checksum_does_not_alias_flags() {
let e = RedexEntry::new_heap(1, 0, 0, 0, 0xFFFF_FFFF);
assert!(!e.is_inline());
assert_eq!(e.checksum(), CHECKSUM_MASK);
}
#[test]
fn test_flags_are_preserved() {
let e = RedexEntry::new_heap(0, 0, 0, RedexFlags::TOMBSTONE, 0);
let decoded = RedexEntry::from_bytes(&e.to_bytes());
assert_eq!(decoded.flags(), RedexFlags::TOMBSTONE);
}
#[test]
fn test_payload_checksum_deterministic() {
assert_eq!(payload_checksum(b"abc"), payload_checksum(b"abc"));
assert_ne!(payload_checksum(b"abc"), payload_checksum(b"abd"));
assert_eq!(payload_checksum(b"abc") & !CHECKSUM_MASK, 0);
}
#[test]
fn test_non_inline_entry_reports_no_inline_payload() {
let e = RedexEntry::new_heap(0, 4, 100, 0, 0);
assert!(e.inline_payload().is_none());
}
#[test]
#[should_panic(expected = "rejects flags=INLINE")]
fn new_heap_with_inline_flag_panics() {
let _ = RedexEntry::new_heap(0, 4, 100, RedexFlags::INLINE, 0);
}
#[test]
fn new_heap_with_tombstone_flag_succeeds() {
let e = RedexEntry::new_heap(0, 4, 100, RedexFlags::TOMBSTONE, 0);
assert!(!e.is_inline());
}
}