1#[macro_export]
2macro_rules! state {
3 ($acct_ty:ident, $data_ty:ident) => {
5 impl $data_ty {
6 pub const fn get_size() -> usize {
8 8 + core::mem::size_of::<Self>()
9 }
10
11 pub fn unpack(data: &[u8]) -> Result<&Self, ProgramError> {
13 let data = &data[..Self::get_size()];
14 Self::try_from_bytes(data)
15 }
16
17 pub fn unpack_mut(data: &mut [u8]) -> Result<&mut Self, ProgramError> {
19 let data = &mut data[..Self::get_size()];
20 Self::try_from_bytes_mut(data)
21 }
22 }
23
24 account!($acct_ty, $data_ty);
26 };
27}
28
29#[macro_export]
30macro_rules! impl_to_bytes {
31 ($struct_name:ident, $discriminator_name:ident) => {
32 impl $struct_name {
33 pub fn to_bytes(&self) -> Vec<u8> {
34 let mut discriminator = [0u8; 8];
35 discriminator[0] = $discriminator_name::$struct_name as u8;
36 [
37 discriminator.to_vec(),
38 bytemuck::bytes_of(self).to_vec(),
39 ]
40 .concat()
41 }
42 }
43 };
44}
45
46#[macro_export]
47macro_rules! impl_try_from_bytes {
48 ($struct_name:ident, $discriminator_name:ident) => {
49 impl $struct_name {
50 pub fn try_from_bytes(data: &[u8]) -> std::io::Result<&Self> {
51 if data.len() < 8 {
52 return Err(std::io::Error::new(
53 std::io::ErrorKind::InvalidData,
54 "Data too short for discriminator",
55 ));
56 }
57 let discriminator = data[0];
58 if discriminator != $discriminator_name::$struct_name as u8 {
59 return Err(std::io::Error::new(
60 std::io::ErrorKind::InvalidData,
61 format!(
62 "Invalid discriminator: expected {}, got {}",
63 $discriminator_name::$struct_name as u8,
64 discriminator
65 ),
66 ));
67 }
68 let struct_size = std::mem::size_of::<Self>();
69 if data.len() < 8 + struct_size {
70 return Err(std::io::Error::new(
71 std::io::ErrorKind::InvalidData,
72 format!(
73 "Data too short: expected at least {} bytes, got {}",
74 8 + struct_size,
75 data.len()
76 ),
77 ));
78 }
79 bytemuck::try_from_bytes::<Self>(&data[8..8 + struct_size]).map_err(|e| {
80 std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string())
81 })
82 }
83 }
84 };
85}
86
87#[macro_export]
88macro_rules! event {
89 ($discriminator_name:ident, $struct_name:ident) => {
90 $crate::impl_to_bytes!($struct_name, $discriminator_name);
91 $crate::impl_try_from_bytes!($struct_name, $discriminator_name);
92
93 impl $struct_name {
94 const DISCRIMINATOR_SIZE: usize = 8;
95
96 pub fn size_of() -> usize {
97 core::mem::size_of::<Self>() + Self::DISCRIMINATOR_SIZE
98 }
99
100 pub fn log(&self) {
101 solana_program::log::sol_log_data(&[&self.to_bytes()]);
102 }
103 }
104 };
105}