use hopper_runtime::{ProgramError, ProgramResult};
#[inline(always)]
pub fn check_state(data: &[u8], offset: usize, expected: u8) -> ProgramResult {
if offset >= data.len() {
return Err(ProgramError::AccountDataTooSmall);
}
if data[offset] != expected {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
#[inline(always)]
pub fn check_state_not(data: &[u8], offset: usize, rejected: u8) -> ProgramResult {
if offset >= data.len() {
return Err(ProgramError::AccountDataTooSmall);
}
if data[offset] == rejected {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
#[inline(always)]
pub fn check_state_in(data: &[u8], offset: usize, allowed: &[u8]) -> ProgramResult {
if offset >= data.len() {
return Err(ProgramError::AccountDataTooSmall);
}
let current = data[offset];
let mut i = 0;
while i < allowed.len() {
if current == allowed[i] {
return Ok(());
}
i += 1;
}
Err(ProgramError::InvalidAccountData)
}
#[inline(always)]
pub fn check_state_transition(
current: u8,
next: u8,
valid_transitions: &[(u8, u8)],
) -> ProgramResult {
let mut i = 0;
while i < valid_transitions.len() {
if valid_transitions[i].0 == current && valid_transitions[i].1 == next {
return Ok(());
}
i += 1;
}
Err(ProgramError::InvalidAccountData)
}
#[inline(always)]
pub fn write_state(data: &mut [u8], offset: usize, new_state: u8) -> ProgramResult {
if offset >= data.len() {
return Err(ProgramError::AccountDataTooSmall);
}
data[offset] = new_state;
Ok(())
}
#[inline(always)]
pub fn zero_bytes(data: &mut [u8]) {
let mut i = 0;
while i < data.len() {
data[i] = 0;
i += 1;
}
}
#[inline(always)]
pub fn write_version(data: &mut [u8], version: u8) -> ProgramResult {
if data.len() < 2 {
return Err(ProgramError::AccountDataTooSmall);
}
data[1] = version;
Ok(())
}
#[inline(always)]
pub fn write_disc(data: &mut [u8], disc: u8) -> ProgramResult {
if data.is_empty() {
return Err(ProgramError::AccountDataTooSmall);
}
data[0] = disc;
Ok(())
}
#[inline(always)]
pub fn write_layout_id(data: &mut [u8], layout_id: &[u8; 8]) -> ProgramResult {
if data.len() < 12 {
return Err(ProgramError::AccountDataTooSmall);
}
data[4..12].copy_from_slice(layout_id);
Ok(())
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ExtensionRegion<const N: usize> {
pub bytes: [u8; N],
}
impl<const N: usize> Default for ExtensionRegion<N> {
fn default() -> Self {
Self { bytes: [0u8; N] }
}
}
impl<const N: usize> ExtensionRegion<N> {
pub const SIZE: usize = N;
#[inline(always)]
pub const fn zeroed() -> Self {
Self { bytes: [0u8; N] }
}
}