1use hopper_runtime::error::ProgramError;
7
8#[inline]
13pub fn check_state_transition(
14 current: u8,
15 next: u8,
16 valid_transitions: &[(u8, u8)],
17) -> Result<(), ProgramError> {
18 for &(from, to) in valid_transitions {
19 if from == current && to == next {
20 return Ok(());
21 }
22 }
23 Err(ProgramError::InvalidAccountData)
24}
25
26#[inline(always)]
28pub fn check_state(data: &[u8], offset: usize, expected: u8) -> Result<(), ProgramError> {
29 if offset >= data.len() {
30 return Err(ProgramError::AccountDataTooSmall);
31 }
32 if data[offset] != expected {
33 return Err(ProgramError::InvalidAccountData);
34 }
35 Ok(())
36}
37
38#[inline(always)]
40pub fn check_state_not(data: &[u8], offset: usize, rejected: u8) -> Result<(), ProgramError> {
41 if offset >= data.len() {
42 return Err(ProgramError::AccountDataTooSmall);
43 }
44 if data[offset] == rejected {
45 return Err(ProgramError::InvalidAccountData);
46 }
47 Ok(())
48}
49
50#[inline]
52pub fn check_state_in(data: &[u8], offset: usize, allowed: &[u8]) -> Result<(), ProgramError> {
53 if offset >= data.len() {
54 return Err(ProgramError::AccountDataTooSmall);
55 }
56 let state = data[offset];
57 for &a in allowed {
58 if state == a {
59 return Ok(());
60 }
61 }
62 Err(ProgramError::InvalidAccountData)
63}
64
65#[inline]
67pub fn transition_state(
68 data: &mut [u8],
69 offset: usize,
70 next: u8,
71 valid_transitions: &[(u8, u8)],
72) -> Result<(), ProgramError> {
73 if offset >= data.len() {
74 return Err(ProgramError::AccountDataTooSmall);
75 }
76 let current = data[offset];
77 check_state_transition(current, next, valid_transitions)?;
78 data[offset] = next;
79 Ok(())
80}