1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use crate::accounts::account_header::AccountHeader;
use crate::accounts::devol_account::DevolAccount;
use crate::accounts::devol_regular_account::DevolRegularAccount;
use crate::accounts::mints::mint::Mint;

pub const MINTS_ACCOUNT_VERSION_OFFSET: usize = 0;
pub const MINTS_ACCOUNT_ROOT_ADDRESS_OFFSET: usize = 8;
pub const MINTS_ACCOUNT_COUNT_OFFSET: usize = 40;
pub const MINTS_ACCOUNT_DATA_OFFSET: usize = 44;
pub const MINTS_ACCOUNT_SIZE: usize = 4140;
pub const MINTS_ACCOUNT_TAG: u8 = 1;
pub const MINTS_ACCOUNT_VERSION: u32 = 3;
pub const MAX_MINTS_COUNT: usize = 32;

#[derive(Clone, Copy)]
#[repr(C)]
pub struct MintsAccount {
    pub header: AccountHeader, // 40 bytes
    pub count: u32, // 4 bytes
    pub data: [Mint; MAX_MINTS_COUNT],
}

impl DevolRegularAccount for MintsAccount {}
impl DevolAccount for MintsAccount {
    #[inline(always)]
    fn expected_size() -> usize { MINTS_ACCOUNT_SIZE }

    #[inline(always)]
    fn expected_tag() -> u8 { MINTS_ACCOUNT_TAG }

    #[inline(always)]
    fn expected_version() -> u32 { MINTS_ACCOUNT_VERSION }
}

#[cfg(test)]
impl Default for MintsAccount {
    fn default() -> Self {
        Self {
            header: AccountHeader::default(),
            count: 0,
            data: [Mint::default(); MAX_MINTS_COUNT],
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::mem;
    use crate::accounts::mints::mint::{MINT_SIZE};

    #[test]
    fn test_root_account_offsets() {
        let account = MintsAccount::default();

        for i in 0..MAX_MINTS_COUNT {
            let mint = &account.data[i];
            let mint_ptr = mint as *const _;
            let expected_ptr = account.data.as_ptr() as usize + i * MINT_SIZE;
            assert_eq!(mint_ptr as usize, expected_ptr, "Mint offset is incorrect for index {}", i);
        }

        let base_ptr = &account as *const _ as usize;
        // checking fields size and offset
        assert_eq!(&account.header as *const _ as usize - base_ptr, MINTS_ACCOUNT_VERSION_OFFSET);
        assert_eq!(&account.count as *const _ as usize - base_ptr, MINTS_ACCOUNT_COUNT_OFFSET);
        assert_eq!(&account.data as *const _ as usize - base_ptr, MINTS_ACCOUNT_DATA_OFFSET);

        // checking total size
        assert_eq!(mem::size_of::<MintsAccount>(), MINTS_ACCOUNT_SIZE);
    }
}