quatzal-storage 0.1.0

Sharded LSM row-storage engine for Quatzal: WAL, snapshots, and crash recovery on io_uring (Linux only).
// SPDX-License-Identifier: Apache-2.0
//! `[len:u32][payload]` framing shared by the WAL and SSTable file formats.

use quatzal_schema::{UaceError, UaceResult};

pub(crate) fn frame(payload: &[u8]) -> Vec<u8> {
    let mut out = Vec::with_capacity(4 + payload.len());
    out.extend_from_slice(&(payload.len() as u32).to_le_bytes());
    out.extend_from_slice(payload);
    out
}

pub(crate) fn unframe(buf: &[u8]) -> UaceResult<(&[u8], usize)> {
    if buf.len() < 4 {
        return Err(UaceError::Codec("truncated frame length".into()));
    }
    let len = u32::from_le_bytes(buf[0..4].try_into().unwrap()) as usize;
    if buf.len() < 4 + len {
        return Err(UaceError::Codec("truncated frame payload".into()));
    }
    Ok((&buf[4..4 + len], 4 + len))
}

/// Walk every framed record in `bytes`, calling `f(payload)` for each.
pub(crate) fn for_each_framed<'a>(
    bytes: &'a [u8],
    mut f: impl FnMut(&'a [u8]) -> UaceResult<()>,
) -> UaceResult<()> {
    let mut pos = 0usize;
    while pos < bytes.len() {
        let (payload, consumed) = unframe(&bytes[pos..])?;
        f(payload)?;
        pos += consumed;
    }
    Ok(())
}