Trait spl_type_length_value::state::TlvState
source · 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§
Provided Methods§
sourcefn get_value<V: SplDiscriminate + Pod>(&self) -> Result<&V, ProgramError>
fn get_value<V: SplDiscriminate + Pod>(&self) -> Result<&V, ProgramError>
Unpack a portion of the TLV data as the desired Pod type
sourcefn get_bytes<V: SplDiscriminate>(&self) -> Result<&[u8], ProgramError>
fn get_bytes<V: SplDiscriminate>(&self) -> Result<&[u8], ProgramError>
Unpack a portion of the TLV data as bytes
sourcefn get_discriminators(&self) -> Result<Vec<ArrayDiscriminator>, ProgramError>
fn get_discriminators(&self) -> Result<Vec<ArrayDiscriminator>, ProgramError>
Iterates through the TLV entries, returning only the types
sourcefn get_base_len() -> usize
fn get_base_len() -> usize
Get the base size required for TLV data