Skip to main content

typhoon_context/args/
borsh.rs

1use {
2    crate::HandlerContext, borsh::BorshDeserialize, solana_account_view::AccountView,
3    solana_address::Address, solana_program_error::ProgramError, typhoon_errors::Error,
4};
5
6pub struct BorshArg<T>(pub T);
7
8impl<T> HandlerContext<'_, '_, '_> for BorshArg<T>
9where
10    T: BorshDeserialize,
11{
12    #[inline(always)]
13    fn from_entrypoint(
14        _program_id: &Address,
15        _accounts: &mut &[AccountView],
16        instruction_data: &mut &[u8],
17    ) -> Result<Self, Error> {
18        let arg = T::deserialize(instruction_data).map_err(|_| ProgramError::BorshIoError)?;
19
20        Ok(BorshArg(arg))
21    }
22}
23
24#[cfg(test)]
25mod tests {
26    use {super::*, borsh::BorshSerialize};
27
28    #[test]
29    fn test_borsh_arg_deserialization() {
30        let mut instruction_data = [0_u8; 8];
31        42_u64
32            .serialize(&mut instruction_data.as_mut_slice())
33            .unwrap();
34        assert_eq!(instruction_data, [42, 0, 0, 0, 0, 0, 0, 0]);
35        let mut accounts: &[AccountView] = &[];
36
37        let mut instruction_data_slice = instruction_data.as_slice();
38        let result: BorshArg<u64> = BorshArg::from_entrypoint(
39            &Address::default(),
40            &mut accounts,
41            &mut instruction_data_slice,
42        )
43        .unwrap_or(BorshArg(0));
44        assert_eq!(result.0, 42);
45        assert_eq!(instruction_data_slice.len(), 0);
46    }
47}