jito_bytemuck/lib.rs
1//! Trait that can be used when working with Solana structs that are used as accounts.
2
3pub mod types;
4
5use bytemuck::Pod;
6pub use jito_account_traits_derive::AccountDeserialize;
7use solana_program::{msg, program_error::ProgramError};
8
9pub trait Discriminator {
10 const DISCRIMINATOR: u8;
11}
12
13pub trait AccountDeserialize: Sized + Pod + Discriminator {
14 /// Deserialize the account data into a struct.
15 /// It assumes the first byte is the discriminator and the next seven bytes are reserved.
16 /// The rest of the data is deserialized into the struct.
17 ///
18 /// # Arguments
19 /// * `data` - The account data to deserialize
20 ///
21 /// # Returns
22 /// * `Result<&Self, ProgramError>` - The deserialized struct as a reference or an error
23 fn try_from_slice_unchecked(data: &[u8]) -> Result<&Self, ProgramError> {
24 if data.first() != Some(&Self::DISCRIMINATOR) {
25 msg!(
26 "Discriminator is invalid; expected {}, got {}",
27 Self::DISCRIMINATOR,
28 data.first().unwrap()
29 );
30 return Err(ProgramError::InvalidAccountData);
31 }
32 bytemuck::try_from_bytes(&data[8..]).map_err(|_| ProgramError::InvalidAccountData)
33 }
34
35 /// Deserialize the account data into a mutable struct.
36 /// It assumes the first byte is the discriminator and the next seven bytes are reserved.
37 /// The rest of the data is deserialized into the struct.
38 ///
39 /// # Arguments
40 /// * `data` - The account data to deserialize
41 ///
42 /// # Returns
43 /// * `Result<&mut Self, ProgramError>` - The deserialized struct as a reference or an error
44 fn try_from_slice_unchecked_mut(data: &mut [u8]) -> Result<&mut Self, ProgramError> {
45 if data.first() != Some(&Self::DISCRIMINATOR) {
46 msg!(
47 "Discriminator is invalid; expected {}, got {}",
48 Self::DISCRIMINATOR,
49 data.first().unwrap()
50 );
51 return Err(ProgramError::InvalidAccountData);
52 }
53 bytemuck::try_from_bytes_mut(&mut data[8..]).map_err(|_| ProgramError::InvalidAccountData)
54 }
55}