cbe_sdk/
account_utils.rs

1//! Useful extras for `Account` state.
2
3use {
4    crate::{
5        account::{Account, AccountSharedData},
6        instruction::InstructionError,
7    },
8    bincode::ErrorKind,
9    std::cell::Ref,
10};
11
12/// Convenience trait to covert bincode errors to instruction errors.
13pub trait StateMut<T> {
14    fn state(&self) -> Result<T, InstructionError>;
15    fn set_state(&mut self, state: &T) -> Result<(), InstructionError>;
16}
17pub trait State<T> {
18    fn state(&self) -> Result<T, InstructionError>;
19    fn set_state(&self, state: &T) -> Result<(), InstructionError>;
20}
21
22impl<T> StateMut<T> for Account
23where
24    T: serde::Serialize + serde::de::DeserializeOwned,
25{
26    fn state(&self) -> Result<T, InstructionError> {
27        self.deserialize_data()
28            .map_err(|_| InstructionError::InvalidAccountData)
29    }
30    fn set_state(&mut self, state: &T) -> Result<(), InstructionError> {
31        self.serialize_data(state).map_err(|err| match *err {
32            ErrorKind::SizeLimit => InstructionError::AccountDataTooSmall,
33            _ => InstructionError::GenericError,
34        })
35    }
36}
37
38impl<T> StateMut<T> for AccountSharedData
39where
40    T: serde::Serialize + serde::de::DeserializeOwned,
41{
42    fn state(&self) -> Result<T, InstructionError> {
43        self.deserialize_data()
44            .map_err(|_| InstructionError::InvalidAccountData)
45    }
46    fn set_state(&mut self, state: &T) -> Result<(), InstructionError> {
47        self.serialize_data(state).map_err(|err| match *err {
48            ErrorKind::SizeLimit => InstructionError::AccountDataTooSmall,
49            _ => InstructionError::GenericError,
50        })
51    }
52}
53
54impl<T> StateMut<T> for Ref<'_, AccountSharedData>
55where
56    T: serde::Serialize + serde::de::DeserializeOwned,
57{
58    fn state(&self) -> Result<T, InstructionError> {
59        self.deserialize_data()
60            .map_err(|_| InstructionError::InvalidAccountData)
61    }
62    fn set_state(&mut self, _state: &T) -> Result<(), InstructionError> {
63        panic!("illegal");
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use {
70        super::*,
71        crate::{account::AccountSharedData, pubkey::Pubkey},
72    };
73
74    #[test]
75    fn test_account_state() {
76        let state = 42u64;
77
78        assert!(AccountSharedData::default().set_state(&state).is_err());
79        let res = AccountSharedData::default().state() as Result<u64, InstructionError>;
80        assert!(res.is_err());
81
82        let mut account = AccountSharedData::new(0, std::mem::size_of::<u64>(), &Pubkey::default());
83
84        assert!(account.set_state(&state).is_ok());
85        let stored_state: u64 = account.state().unwrap();
86        assert_eq!(stored_state, state);
87    }
88}