1#![deny(missing_docs)]
2extern crate solana_program;
10use arrayref::{array_refs, mut_array_refs};
11use solana_program::{
12 declare_id, entrypoint::MAX_PERMITTED_DATA_INCREASE, entrypoint::SUCCESS,
13 program_error::ProgramError, pubkey::Pubkey,
14};
15use std::{
16 mem::{align_of, size_of},
17 ptr::read,
18 slice::{from_raw_parts, from_raw_parts_mut},
19};
20
21declare_id!("shmem4EWT2sPdVGvTZCzXXRAURL9G5vpPxNwSeKhHUL");
22
23fn fast_copy(mut src: &[u8], mut dst: &mut [u8]) {
25 while src.len() >= 8 {
26 #[allow(clippy::ptr_offset_with_cast)]
27 let (src_word, src_rem) = array_refs![src, 8; ..;];
28 #[allow(clippy::ptr_offset_with_cast)]
29 let (dst_word, dst_rem) = mut_array_refs![dst, 8; ..;];
30 *dst_word = *src_word;
31 src = src_rem;
32 dst = dst_rem;
33 }
34 unsafe {
35 std::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len());
36 }
37}
38
39unsafe fn deserialize_input_parameters<'a>(
43 input: *mut u8,
44) -> Result<(&'a mut [u8], &'a [u8]), u64> {
45 let num_accounts = read(input as *const u64);
47 if num_accounts == 0 {
48 return Err(ProgramError::NotEnoughAccountKeys.into());
49 } else if num_accounts > 1 {
50 return Err(ProgramError::InvalidArgument.into());
51 }
52
53 let data_len_offset = size_of::<u64>()
55 + size_of::<u8>()
56 + size_of::<u8>()
57 + size_of::<u8>()
58 + size_of::<u8>()
59 + size_of::<u32>()
60 + size_of::<Pubkey>()
61 + size_of::<Pubkey>()
62 + size_of::<u64>();
63
64 let account_data_len = read(input.add(data_len_offset) as *const usize);
65 let data_ptr = input.add(data_len_offset + size_of::<u64>());
66 let account_data = from_raw_parts_mut(data_ptr, account_data_len);
67
68 let instruction_len_offset = account_data_len
70 + MAX_PERMITTED_DATA_INCREASE
71 + (account_data_len as *const u8).align_offset(align_of::<u128>())
72 + size_of::<u64>();
73
74 let instruction_data_len = read(data_ptr.add(instruction_len_offset) as *const usize);
75 let instruction_data = from_raw_parts(
76 data_ptr.add(instruction_len_offset + size_of::<u64>()),
77 instruction_data_len,
78 );
79
80 Ok((account_data, instruction_data))
81}
82
83#[no_mangle]
94pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 {
95 match deserialize_input_parameters(input) {
96 Ok((account_data, instruction_data)) => {
97 if instruction_data.len() < 8 {
98 return ProgramError::AccountDataTooSmall.into();
99 }
100 #[allow(clippy::ptr_offset_with_cast)]
101 let (offset, content) = array_refs![instruction_data, 8; ..;];
102 let offset = usize::from_le_bytes(*offset);
103 if account_data.len() < offset + content.len() {
104 return ProgramError::AccountDataTooSmall.into();
105 }
106 let data_ptr = account_data.as_mut_ptr() as usize;
107 let data = from_raw_parts_mut((data_ptr + offset) as *mut u8, content.len());
108 fast_copy(content, data);
109 }
110 Err(err) => return err,
111 }
112 SUCCESS
113}