//! useful extras for Account state use { crate::{ account::{Account, AccountSharedData}, instruction::InstructionError, }, bincode::ErrorKind, std::cell::Ref, }; /// Convenience trait to covert bincode errors to instruction errors. pub trait StateMut { fn state(&self) -> Result; fn set_state(&mut self, state: &T) -> Result<(), InstructionError>; } pub trait State { fn state(&self) -> Result; fn set_state(&self, state: &T) -> Result<(), InstructionError>; } impl StateMut for Account where T: serde::Serialize + serde::de::DeserializeOwned, { fn state(&self) -> Result { self.deserialize_data() .map_err(|_| InstructionError::InvalidAccountData) } fn set_state(&mut self, state: &T) -> Result<(), InstructionError> { self.serialize_data(state).map_err(|err| match *err { ErrorKind::SizeLimit => InstructionError::AccountDataTooSmall, _ => InstructionError::GenericError, }) } } impl StateMut for AccountSharedData where T: serde::Serialize + serde::de::DeserializeOwned, { fn state(&self) -> Result { self.deserialize_data() .map_err(|_| InstructionError::InvalidAccountData) } fn set_state(&mut self, state: &T) -> Result<(), InstructionError> { self.serialize_data(state).map_err(|err| match *err { ErrorKind::SizeLimit => InstructionError::AccountDataTooSmall, _ => InstructionError::GenericError, }) } } impl StateMut for Ref<'_, AccountSharedData> where T: serde::Serialize + serde::de::DeserializeOwned, { fn state(&self) -> Result { self.deserialize_data() .map_err(|_| InstructionError::InvalidAccountData) } fn set_state(&mut self, _state: &T) -> Result<(), InstructionError> { panic!("illegal"); } } #[cfg(test)] mod tests { use { super::*, crate::{account::AccountSharedData, pubkey::Pubkey}, }; #[test] fn test_account_state() { let state = 42u64; assert!(AccountSharedData::default().set_state(&state).is_err()); let res = AccountSharedData::default().state() as Result; assert!(res.is_err()); let mut account = AccountSharedData::new(0, std::mem::size_of::(), &Pubkey::default()); assert!(account.set_state(&state).is_ok()); let stored_state: u64 = account.state().unwrap(); assert_eq!(stored_state, state); } }