Skip to main content

TableObject

Trait TableObject 

Source
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§

Source

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.

Implementations on Foreign Types§

Source§

impl TableObject<'_> for Vec<u8>

Source§

fn decode_borrow(data: Cow<'_, [u8]>) -> ReadResult<Self>

Source§

impl<'a> TableObject<'a> for Cow<'a, [u8]>

Source§

fn decode_borrow(data: Cow<'a, [u8]>) -> ReadResult<Self>

Source§

impl<'a> TableObject<'a> for ()

Source§

fn decode_borrow(_: Cow<'a, [u8]>) -> ReadResult<Self>

Source§

impl<'a, const LEN: usize> TableObject<'a> for [u8; LEN]

Source§

fn decode_borrow(data: Cow<'a, [u8]>) -> ReadResult<Self>

Implementors§