solana_stable_layout/
stable_instruction.rs1use {
4 crate::stable_vec::StableVec,
5 solana_instruction::{AccountMeta, Instruction},
6 solana_pubkey::Pubkey,
7 std::fmt::Debug,
8};
9
10#[derive(Debug, PartialEq)]
32#[repr(C)]
33pub struct StableInstruction {
34 pub accounts: StableVec<AccountMeta>,
35 pub data: StableVec<u8>,
36 pub program_id: Pubkey,
37}
38
39impl From<Instruction> for StableInstruction {
40 fn from(other: Instruction) -> Self {
41 Self {
42 accounts: other.accounts.into(),
43 data: other.data.into(),
44 program_id: other.program_id,
45 }
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use {
52 super::*,
53 memoffset::offset_of,
54 std::mem::{align_of, size_of},
55 };
56
57 #[test]
58 fn test_memory_layout() {
59 assert_eq!(offset_of!(StableInstruction, accounts), 0);
60 assert_eq!(offset_of!(StableInstruction, data), 24);
61 assert_eq!(offset_of!(StableInstruction, program_id), 48);
62 assert_eq!(align_of::<StableInstruction>(), 8);
63 assert_eq!(size_of::<StableInstruction>(), 24 + 24 + 32);
64
65 let program_id = Pubkey::new_unique();
66 let account_meta1 = AccountMeta {
67 pubkey: Pubkey::new_unique(),
68 is_signer: true,
69 is_writable: false,
70 };
71 let account_meta2 = AccountMeta {
72 pubkey: Pubkey::new_unique(),
73 is_signer: false,
74 is_writable: true,
75 };
76 let accounts = vec![account_meta1, account_meta2];
77 let data = vec![1, 2, 3, 4, 5];
78 let instruction = Instruction {
79 program_id,
80 accounts: accounts.clone(),
81 data: data.clone(),
82 };
83 let instruction = StableInstruction::from(instruction);
84
85 let instruction_addr = &instruction as *const _ as u64;
86
87 let accounts_ptr = instruction_addr as *const StableVec<AccountMeta>;
88 assert_eq!(unsafe { &*accounts_ptr }, &accounts);
89
90 let data_ptr = (instruction_addr + 24) as *const StableVec<u8>;
91 assert_eq!(unsafe { &*data_ptr }, &data);
92
93 let pubkey_ptr = (instruction_addr + 48) as *const Pubkey;
94 assert_eq!(unsafe { *pubkey_ptr }, program_id);
95 }
96}