pub trait TableObject<'a>: Sized {
// Required method
fn decode_borrow(data: Cow<'a, [u8]>) -> ReadResult<Self>;
}Expand description
Decodes values read from the database into Rust types.
Implement this trait to enable reading custom types directly from MDBX.
The lifetime parameter 'a allows types to borrow data from the
transaction when appropriate (e.g., Cow<'a, [u8]>).
§Implementation Guide
For most types, only implement decode_borrow. An
internal function decode_val is provided to handle zero-copy borrowing.
Implementing it is STRONGLY DISCOURAGED. Zero-copy borrowing can be
achieved by implementing decode_borrow.
§Zero-copy Deserialization
MDBX supports zero-copy deserialization for types that can borrow data
directly from the database (like Cow<'a, [u8]>). Read-only transactions
ALWAYS support borrowing, while read-write transactions require a check
to see if the data is “dirty” (modified but not yet committed). If the page
containing the data is dirty, a copy must be made before borrowing.
TableObject::decode_borrow is the main method to implement. It receives
a Cow<'a, [u8]> which may be either borrowed or owned data, depending on
the transaction type and data state. Implementations may choose to split
the data further, copy it, or use it as-is.
use signet_libmdbx::{TableObject, ReadResult, MdbxError};
// A zero-copy wrapper around a u32 stored in little-endian format.
struct MyZeroCopyU32<'a> (Cow<'a, [u8]>);
impl<'a> TableObject<'a> for MyZeroCopyU32<'a> {
fn decode_borrow(data: Cow<'a, [u8]>) -> ReadResult<Self> {
if data.len() < 4 {
return Err(MdbxError::DecodeErrorLenDiff.into());
}
Ok(MyZeroCopyU32(data))
}
}
impl MyZeroCopyU32<'_> {
/// Reads a u32 from the start of the data.
pub fn read_u32(&self) -> u32 {
let bytes = &self.0[..4];
u32::from_le_bytes(bytes.try_into().unwrap())
}
}§Fixed-Size Types
struct Hash([u8; 32]);
impl TableObject<'_> for Hash {
fn decode_borrow(data: Cow<'_, [u8]>) -> ReadResult<Self> {
let arr: [u8; 32] = data.as_ref().try_into()
.map_err(|_| MdbxError::DecodeErrorLenDiff)?;
Ok(Self(arr))
}
}§Variable-Size Types
struct VarInt(u64);
impl TableObject<'_> for VarInt {
fn decode_borrow(data: Cow<'_, [u8]>) -> ReadResult<Self> {
// Example: decode LEB128 or similar
let value = data.iter()
.take(8)
.enumerate()
.fold(0u64, |acc, (i, &b)| acc | ((b as u64) << (i * 8)));
Ok(Self(value))
}
}Required Methods§
Sourcefn decode_borrow(data: Cow<'a, [u8]>) -> ReadResult<Self>
fn decode_borrow(data: Cow<'a, [u8]>) -> ReadResult<Self>
Creates the object from a Cow of bytes. This allows for efficient
handling of both owned and borrowed data.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.