1use super::*;
2use borsh::{BorshDeserialize, BorshSerialize};
3use solana_program::clock::UnixTimestamp;
4
5#[derive(BorshSerialize, BorshDeserialize, Debug, Clone)]
6pub struct Timelock<T: BorshDeserialize + BorshSerialize + MaxSerializedLen, const N: usize>(
7 Vec<LockedItem<T>>,
8);
9
10impl<T, const N: usize> MaxSerializedLen for Timelock<T, N>
11where
12 T: BorshSerialize + BorshDeserialize + MaxSerializedLen,
13{
14 const MAX_SERIALIZED_LEN: usize = 4 + N * (T::MAX_SERIALIZED_LEN + 8); }
16
17impl<T, const N: usize> Timelock<T, N>
20where
21 T: BorshSerialize + BorshDeserialize + MaxSerializedLen,
22{
23 pub fn new() -> Self {
24 Self(Vec::new())
25 }
26
27 pub fn lock(&mut self, item: T, expiration_date: UnixTimestamp) -> Result<(), TimelockError> {
28 if self.0.len() < N {
29 self.0.push(LockedItem {
30 item,
31 expires: expiration_date,
32 });
33 Ok(())
34 } else {
35 Err(TimelockError::TimelockStorageFull)
36 }
37 }
38
39 pub fn locked_items(&self) -> &Vec<LockedItem<T>> {
40 &self.0
41 }
42
43 pub fn locked_items_mut(&mut self) -> &mut Vec<LockedItem<T>> {
44 &mut self.0
45 }
46
47 pub fn len(&self) -> usize {
48 self.0.len()
49 }
50
51 pub fn is_empty(&self) -> bool {
52 self.0.is_empty()
53 }
54
55 pub fn max_len(&self) -> usize {
56 N
57 }
58}
59
60impl<T, const N: usize> Default for Timelock<T, N>
61where
62 T: BorshSerialize + BorshDeserialize + MaxSerializedLen,
63{
64 fn default() -> Self {
65 Self::new()
66 }
67}
68
69#[derive(Debug)]
70pub enum TimelockError {
71 TimelockStorageFull,
72}
73
74#[cfg(test)]
75mod test {
76 use super::*;
77
78 #[derive(BorshSerialize, BorshDeserialize, Clone, Copy, Debug)]
79 struct Dummy {
80 a: u64,
81 b: i32,
82 c: [u8; 5],
83 }
84
85 impl MaxSerializedLen for Dummy {
86 const MAX_SERIALIZED_LEN: usize = 17;
87 }
88
89 const L: usize = 10;
90
91 #[test]
92 #[rustfmt::skip]
93 fn serialized_len() {
94 let mut timelock = Timelock::<Dummy, L>::new();
95 for i in 0..L {
96 timelock.lock(Dummy { a: 4, b: -3423, c: [0_u8; 5] }, 32445 + i as UnixTimestamp).unwrap();
97 }
98 assert_eq!(Timelock::<Dummy, L>::MAX_SERIALIZED_LEN, timelock.try_to_vec().unwrap().len());
99
100 assert!(timelock.lock(Dummy { a: 4, b: -3423, c: [0_u8; 5] }, 32445).is_err());
102 assert_eq!(timelock.len(), L);
103 }
104}