typhoon_context/args/
bytemuck.rs1use {
2 crate::HandlerContext,
3 bytemuck::AnyBitPattern,
4 pinocchio::{account_info::AccountInfo, pubkey::Pubkey},
5 typhoon_errors::{Error, ErrorCode},
6};
7
8#[derive(Debug)]
9pub struct Arg<'a, T>(pub &'a T);
10
11impl<'c, T> HandlerContext<'_, '_, 'c> for Arg<'c, T>
12where
13 T: AnyBitPattern,
14{
15 #[inline(always)]
16 fn from_entrypoint(
17 _program_id: &Pubkey,
18 _accounts: &mut &[AccountInfo],
19 instruction_data: &mut &'c [u8],
20 ) -> Result<Self, Error> {
21 let len = core::mem::size_of::<T>();
22
23 if len > instruction_data.len() {
24 return Err(ErrorCode::InvalidDataLength.into());
25 }
26
27 let (arg_data, remaining) = unsafe { instruction_data.split_at_unchecked(len) };
32 let data_ptr = arg_data.as_ptr();
33
34 if data_ptr.align_offset(core::mem::align_of::<T>()) != 0 {
35 return Err(ErrorCode::InvalidDataAlignment.into());
36 }
37
38 let arg: &T = unsafe { &*(data_ptr as *const T) };
39
40 *instruction_data = remaining;
41
42 Ok(Arg(arg))
43 }
44}