use {
borsh::{BorshDeserialize, BorshSchema, BorshSerialize},
solana_program::{
clock::UnixTimestamp,
msg,
program_error::ProgramError,
program_pack::{Pack, Sealed},
},
};
#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, PartialEq)]
pub struct AcceptanceCriteria {
pub tokens_required: u64,
pub deadline: UnixTimestamp,
}
#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, PartialEq)]
pub enum FeatureProposal {
Uninitialized,
Pending(AcceptanceCriteria),
Accepted {
#[allow(dead_code)] tokens_upon_acceptance: u64,
},
Expired,
}
impl Sealed for FeatureProposal {}
impl Pack for FeatureProposal {
const LEN: usize = 17; fn pack_into_slice(&self, dst: &mut [u8]) {
let data = borsh::to_vec(&self).unwrap();
dst[..data.len()].copy_from_slice(&data);
}
fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError> {
let mut mut_src: &[u8] = src;
Self::deserialize(&mut mut_src).map_err(|err| {
msg!(
"Error: failed to deserialize feature proposal account: {}",
err
);
ProgramError::InvalidAccountData
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_packed_len() {
assert_eq!(
FeatureProposal::get_packed_len(),
solana_program::borsh1::get_packed_len::<FeatureProposal>()
);
}
#[test]
fn test_serialize_bytes() {
assert_eq!(borsh::to_vec(&FeatureProposal::Expired).unwrap(), vec![3]);
assert_eq!(
borsh::to_vec(&FeatureProposal::Pending(AcceptanceCriteria {
tokens_required: 0xdeadbeefdeadbeef,
deadline: -1,
}))
.unwrap(),
vec![1, 239, 190, 173, 222, 239, 190, 173, 222, 255, 255, 255, 255, 255, 255, 255, 255],
);
}
#[test]
fn test_serialize_large_slice() {
let mut dst = vec![0xff; 4];
FeatureProposal::Expired.pack_into_slice(&mut dst);
assert_eq!(dst, vec![3, 0xff, 0xff, 0xff]);
}
#[test]
fn state_deserialize_invalid() {
assert_eq!(
FeatureProposal::unpack_from_slice(&[3]),
Ok(FeatureProposal::Expired),
);
assert_eq!(
FeatureProposal::unpack_from_slice(&[3, 0xff, 0xff, 0xff]),
Ok(FeatureProposal::Expired),
);
assert_eq!(
FeatureProposal::unpack_from_slice(&[4]),
Err(ProgramError::InvalidAccountData),
);
}
}