pub fn states_mod_rs() -> &'static str {
r#"pub mod state;
pub mod utils;
pub use state::*;
pub use utils::*;"#
}
pub fn state_rs() -> &'static str {
r#"use super::utils::{load_acc_mut_unchecked, DataLen};
use pinocchio::{error::ProgramError, Address, AccountView, ProgramResult};
use crate::{errors::MyProgramError, instructions::Initialize};
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, shank::ShankAccount)]
pub struct MyState {
pub owner: Address,
}
// Read zero-copy (pointer cast), so the #[repr(C)] layout must be padding-free
// to match the packed borsh the client sends. Add `_padding: [u8; N]` if widened.
const _: () = assert!(
core::mem::size_of::<MyState>() == 32,
"MyState has implicit padding; add explicit _padding fields so its #[repr(C)] layout matches the borsh client"
);
impl DataLen for MyState {
const LEN: usize = core::mem::size_of::<MyState>();
}
impl MyState {
pub const SEED: &'static str = "init";
pub fn validate_pda(bump: u8, pda: &Address, owner: &Address) -> Result<(), ProgramError> {
let seed_with_bump = &[Self::SEED.as_bytes(), owner.as_array().as_slice(), &[bump]];
let derived = Address::create_program_address(seed_with_bump, &crate::ID)?;
if derived != *pda {
return Err(MyProgramError::PdaMismatch.into());
}
Ok(())
}
pub fn initialize(my_stata_acc: &mut AccountView, ix_data: &Initialize) -> ProgramResult {
let my_state =
unsafe { load_acc_mut_unchecked::<MyState>(my_stata_acc.borrow_unchecked_mut()) }?;
my_state.owner = ix_data.owner;
Ok(())
}
}"#
}
pub fn utils_rs() -> &'static str {
r#"use pinocchio::error::ProgramError;
use crate::errors::MyProgramError;
pub trait DataLen {
const LEN: usize;
}
#[inline(always)]
pub unsafe fn load_acc_unchecked<T: DataLen>(bytes: &[u8]) -> Result<&T, ProgramError> {
if bytes.len() != T::LEN {
return Err(ProgramError::InvalidAccountData);
}
Ok(&*(bytes.as_ptr() as *const T))
}
#[inline(always)]
pub unsafe fn load_acc_mut_unchecked<T: DataLen>(bytes: &mut [u8]) -> Result<&mut T, ProgramError> {
if bytes.len() != T::LEN {
return Err(ProgramError::InvalidAccountData);
}
Ok(&mut *(bytes.as_mut_ptr() as *mut T))
}
#[inline(always)]
pub unsafe fn load_ix_data<T: DataLen>(bytes: &[u8]) -> Result<&T, ProgramError> {
if bytes.len() != T::LEN {
return Err(MyProgramError::InvalidInstructionData.into());
}
Ok(&*(bytes.as_ptr() as *const T))
}
pub unsafe fn to_bytes<T: DataLen>(data: &T) -> &[u8] {
core::slice::from_raw_parts(data as *const T as *const u8, T::LEN)
}
pub unsafe fn to_mut_bytes<T: DataLen>(data: &mut T) -> &mut [u8] {
core::slice::from_raw_parts_mut(data as *mut T as *mut u8, T::LEN)
}"#
}