solana-flux-aggregator/program/src/borsh_state.rs

77 lines
2.4 KiB
Rust
Raw Normal View History

2021-02-03 01:59:21 -08:00
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{
2021-02-04 00:22:45 -08:00
account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
2021-02-03 17:50:04 -08:00
program_pack::IsInitialized, sysvar::rent::Rent,
2021-02-03 01:59:21 -08:00
};
pub trait BorshState: BorshDeserialize + BorshSerialize {
2021-02-03 17:50:04 -08:00
fn load(account: &AccountInfo) -> Result<Self, ProgramError> {
let data = (*account.data).borrow();
Self::try_from_slice(&data).map_err(|_| ProgramError::InvalidAccountData)
}
2021-02-03 01:59:21 -08:00
2021-02-03 17:50:04 -08:00
fn save(&self, account: &AccountInfo) -> ProgramResult {
let data = self
.try_to_vec()
.map_err(|_| ProgramError::InvalidAccountData)?;
2021-02-03 01:59:21 -08:00
2021-02-03 17:50:04 -08:00
// FIXME: looks like there is association precedence issue that prevents
// RefMut from being automatically dereferenced.
//
// let dst = &mut account.data.borrow_mut();
//
// Why does it work in an SPL token program though?
//
// Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
let mut dst = (*account.data).borrow_mut();
if dst.len() != data.len() {
return Err(ProgramError::InvalidAccountData);
}
dst.copy_from_slice(&data);
Ok(())
2021-02-03 01:59:21 -08:00
}
2021-02-03 17:50:04 -08:00
fn save_exempt(&self, account: &AccountInfo, rent: &Rent) -> ProgramResult {
let data = self
.try_to_vec()
.map_err(|_| ProgramError::InvalidAccountData)?;
2021-02-03 01:59:21 -08:00
2021-02-03 17:50:04 -08:00
if !rent.is_exempt(account.lamports(), data.len()) {
// FIXME: return a custom error
return Err(ProgramError::InvalidAccountData);
}
2021-02-03 01:59:21 -08:00
2021-02-03 17:50:04 -08:00
let mut dst = (*account.data).borrow_mut();
if dst.len() != data.len() {
// FIXME: return a custom error
return Err(ProgramError::InvalidAccountData);
}
dst.copy_from_slice(&data);
2021-02-03 01:59:21 -08:00
2021-02-03 17:50:04 -08:00
Ok(())
2021-02-03 01:59:21 -08:00
}
}
pub trait InitBorshState: BorshState + IsInitialized {
2021-02-03 17:50:04 -08:00
// type Self = IsInitialized
fn load_initialized(account: &AccountInfo) -> Result<Self, ProgramError> {
let object = Self::load(account)?;
if !object.is_initialized() {
return Err(ProgramError::UninitializedAccount);
}
Ok(object)
2021-02-03 01:59:21 -08:00
}
2021-02-03 17:50:04 -08:00
fn init_uninitialized(account: &AccountInfo) -> Result<Self, ProgramError> {
let object = Self::load(account)?;
if object.is_initialized() {
return Err(ProgramError::AccountAlreadyInitialized);
}
2021-02-03 01:59:21 -08:00
2021-02-03 17:50:04 -08:00
Ok(object)
2021-02-03 01:59:21 -08:00
}
2021-02-03 17:50:04 -08:00
}