pub struct Page {
pub footer: Footer,
pub records: Vec<Vec<u8>>,
/* private fields */
}Expand description
A slabtastic page containing a header, records, offset array, and footer.
§Wire layout
[magic:4 "SLAB"][page_size:4][record data ...][offsets:(n+1)*4][footer:16]The offset array contains (record_count + 1) little-endian u32
values. Each value is a byte position measured from the start of the
page, so the first record always starts at offset 8 (after the 8-byte
header). The extra sentinel offset marks the end of the last record.
§Examples
use slabtastic::{Page, PageType};
let mut page = Page::new(0, PageType::Data);
page.add_record(b"hello");
page.add_record(b"world");
let bytes = page.serialize();
let decoded = Page::deserialize(&bytes).unwrap();
assert_eq!(decoded.record_count(), 2);
assert_eq!(decoded.get_record(0).unwrap(), b"hello");Fields§
The page footer (metadata).
records: Vec<Vec<u8>>The raw record data blobs.
Implementations§
Source§impl Page
impl Page
Sourcepub fn add_record(&mut self, data: &[u8])
pub fn add_record(&mut self, data: &[u8])
Append a record to this page.
Sourcepub fn add_record_owned(&mut self, data: Vec<u8>)
pub fn add_record_owned(&mut self, data: Vec<u8>)
Append a record by taking ownership of its bytes — no clone.
Identical to add_record but accepts the
record as Vec<u8> rather than &[u8]. Callers that already
own the bytes (e.g. predicate-merge phases that just produced
the buffer) avoid a full record-sized memcpy per call. On a
10K-predicate × 5 MB-each run this saves ~50 GB of memcpy on
the SlabWriter intake side.
Sourcepub fn serialized_size(&self) -> usize
pub fn serialized_size(&self) -> usize
Compute the total serialized size of this page.
Sourcepub fn serialize(&self) -> Vec<u8> ⓘ
pub fn serialize(&self) -> Vec<u8> ⓘ
Serialize this page to a byte vector.
Layout: [magic:4][page_size:4][records...][offsets:(n+1)*4][footer:16]
Sourcepub fn deserialize(buf: &[u8]) -> Result<Page>
pub fn deserialize(buf: &[u8]) -> Result<Page>
Deserialize a page from a byte buffer.
Sourcepub fn get_record(&self, index: usize) -> Option<&[u8]>
pub fn get_record(&self, index: usize) -> Option<&[u8]>
Get a record by its local (zero-based) index.
Sourcepub fn record_count(&self) -> usize
pub fn record_count(&self) -> usize
Return the number of records in this page.
Sourcepub fn start_ordinal(&self) -> i64
pub fn start_ordinal(&self) -> i64
Return the starting ordinal for this page.
Sourcepub fn record_count_from_buf(buf: &[u8]) -> Result<usize>
pub fn record_count_from_buf(buf: &[u8]) -> Result<usize>
Read the record count from a serialized page buffer by inspecting only the footer bytes. No heap allocation.
The record count is stored as a 3-byte unsigned LE integer at
footer offset 5–7 (bytes [len-11..len-8] of the page buffer).
§Errors
SlabError::TruncatedPageif the buffer is too small for a header + footer.
Sourcepub fn get_record_ref_from_buf(
buf: &[u8],
local_index: usize,
record_count: usize,
) -> Result<&[u8]>
pub fn get_record_ref_from_buf( buf: &[u8], local_index: usize, record_count: usize, ) -> Result<&[u8]>
Return a borrowed slice of a single record from a serialized page buffer without deserializing the entire page.
Like get_record_from_buf but returns
&[u8] instead of Vec<u8>, eliminating the per-record heap
allocation. The record_count parameter avoids re-parsing the
footer on every call when iterating all records in a page.
Magic validation is intentionally skipped since callers are expected to have obtained the buffer through a validated path.
§Errors
SlabError::TruncatedPageif the buffer is too small.SlabError::OrdinalNotFoundiflocal_indexis out of range.
Sourcepub fn get_record_from_buf(buf: &[u8], local_index: usize) -> Result<Vec<u8>>
pub fn get_record_from_buf(buf: &[u8], local_index: usize) -> Result<Vec<u8>>
Extract a single record from a serialized page buffer without deserializing the entire page.
This reads only the footer and the two offset entries needed to
locate the record at local_index, then copies just that
record’s bytes. No Vec<Vec<u8>> allocation for all records and
no parsing of all N+1 offsets.
Magic validation is intentionally skipped since callers are expected to have obtained the buffer through a validated path.
Note: SlabReader::get performs
targeted I/O directly (reading only geometry + record bytes)
rather than buffering the full page. This method is useful when
a full page buffer is already in memory for other reasons.
§Errors
SlabError::TruncatedPageif the buffer is too small.SlabError::OrdinalNotFoundiflocal_indexis out of range (uses ordinal −1 as a placeholder since the caller maps ordinals to local indices).