spl_feature_proposal/
state.rs1use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
3use solana_program::{
4 clock::UnixTimestamp,
5 info,
6 program_error::ProgramError,
7 program_pack::{Pack, Sealed},
8};
9
10#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, PartialEq)]
12pub struct AcceptanceCriteria {
13 pub tokens_required: u64,
16
17 pub deadline: UnixTimestamp,
19}
20
21#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, PartialEq)]
23pub enum FeatureProposal {
24 Uninitialized,
26 Pending(AcceptanceCriteria),
28 Accepted {
30 #[allow(dead_code)] tokens_upon_acceptance: u64,
33 },
34 Expired,
36}
37impl Sealed for FeatureProposal {}
38
39impl Pack for FeatureProposal {
40 const LEN: usize = 17; fn pack_into_slice(&self, dst: &mut [u8]) {
43 let data = self.try_to_vec().unwrap();
44 dst[..data.len()].copy_from_slice(&data);
45 }
46
47 fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError> {
48 let mut mut_src: &[u8] = src;
49 Self::deserialize(&mut mut_src).map_err(|err| {
50 info!(&format!(
51 "Error: failed to deserialize feature proposal account: {}",
52 err
53 ));
54 ProgramError::InvalidAccountData
55 })
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use crate::borsh_utils;
63
64 #[test]
65 fn test_get_packed_len() {
66 assert_eq!(
67 FeatureProposal::get_packed_len(),
68 borsh_utils::get_packed_len::<FeatureProposal>()
69 );
70 }
71
72 #[test]
73 fn test_serialize_bytes() {
74 assert_eq!(FeatureProposal::Expired.try_to_vec().unwrap(), vec![3]);
75
76 assert_eq!(
77 FeatureProposal::Pending(AcceptanceCriteria {
78 tokens_required: 0xdeadbeefdeadbeef,
79 deadline: -1,
80 })
81 .try_to_vec()
82 .unwrap(),
83 vec![1, 239, 190, 173, 222, 239, 190, 173, 222, 255, 255, 255, 255, 255, 255, 255, 255],
84 );
85 }
86
87 #[test]
88 fn test_serialize_large_slice() {
89 let mut dst = vec![0xff; 4];
90 FeatureProposal::Expired.pack_into_slice(&mut dst);
91
92 assert_eq!(dst, vec![3, 0xff, 0xff, 0xff]);
94 }
95
96 #[test]
97 fn state_deserialize_invalid() {
98 assert_eq!(
99 FeatureProposal::unpack_from_slice(&[3]),
100 Ok(FeatureProposal::Expired),
101 );
102
103 assert_eq!(
105 FeatureProposal::unpack_from_slice(&[3, 0xff, 0xff, 0xff]),
106 Ok(FeatureProposal::Expired),
107 );
108
109 assert_eq!(
110 FeatureProposal::unpack_from_slice(&[4]),
111 Err(ProgramError::InvalidAccountData),
112 );
113 }
114}