pub trait TlvState {
    // Required method
    fn get_data(&self) -> &[u8] ;

    // Provided methods
    fn get_value<V: SplDiscriminate + Pod>(&self) -> Result<&V, ProgramError> { ... }
    fn get_bytes<V: SplDiscriminate>(&self) -> Result<&[u8], ProgramError> { ... }
    fn get_discriminators(
        &self
    ) -> Result<Vec<ArrayDiscriminator>, ProgramError> { ... }
    fn get_base_len() -> usize { ... }
}
Expand description

Trait for all TLV state

Stores data as any number of type-length-value structures underneath, where:

  • the “type” is an ArrayDiscriminator, 8 bytes
  • the “length” is a Length, 4 bytes
  • the “value” is a slab of “length” bytes

With this structure, it’s possible to hold onto any number of entries with unique discriminators, provided that the total underlying data has enough bytes for every entry.

For example, if we have two distinct types, one which is an 8-byte array of value [0, 1, 0, 0, 0, 0, 0, 0] and discriminator [1, 1, 1, 1, 1, 1, 1, 1], and another which is just a single u8 of value 4 with the discriminator [2, 2, 2, 2, 2, 2, 2, 2], we can deserialize this buffer as follows:

use {
    bytemuck::{Pod, Zeroable},
    spl_discriminator::{ArrayDiscriminator, SplDiscriminate},
    spl_type_length_value::state::{TlvState, TlvStateBorrowed, TlvStateMut},
};
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
struct MyPodValue {
    data: [u8; 8],
}
impl SplDiscriminate for MyPodValue {
    const SPL_DISCRIMINATOR: ArrayDiscriminator = ArrayDiscriminator::new([1; ArrayDiscriminator::LENGTH]);
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
struct MyOtherPodValue {
    data: u8,
}
impl SplDiscriminate for MyOtherPodValue {
    const SPL_DISCRIMINATOR: ArrayDiscriminator = ArrayDiscriminator::new([2; ArrayDiscriminator::LENGTH]);
}
let buffer = [
  1, 1, 1, 1, 1, 1, 1, 1, // first type's discriminator
  8, 0, 0, 0,             // first type's length
  0, 1, 0, 0, 0, 0, 0, 0, // first type's value
  2, 2, 2, 2, 2, 2, 2, 2, // second type's discriminator
  1, 0, 0, 0,             // second type's length
  4,                      // second type's value
];
let state = TlvStateBorrowed::unpack(&buffer).unwrap();
let value = state.get_value::<MyPodValue>().unwrap();
assert_eq!(value.data, [0, 1, 0, 0, 0, 0, 0, 0]);
let value = state.get_value::<MyOtherPodValue>().unwrap();
assert_eq!(value.data, 4);

See the README and tests for more examples on how to use these types.

Required Methods§

source

fn get_data(&self) -> &[u8]

Get the full buffer containing all TLV data

Provided Methods§

source

fn get_value<V: SplDiscriminate + Pod>(&self) -> Result<&V, ProgramError>

Unpack a portion of the TLV data as the desired Pod type

source

fn get_bytes<V: SplDiscriminate>(&self) -> Result<&[u8], ProgramError>

Unpack a portion of the TLV data as bytes

source

fn get_discriminators(&self) -> Result<Vec<ArrayDiscriminator>, ProgramError>

Iterates through the TLV entries, returning only the types

source

fn get_base_len() -> usize

Get the base size required for TLV data

Implementors§