can someone give me a explanation of the usage of repr(C) macro, since in my understanding it simply acts for bridging up the compilation in C, is not wrong?
Further, why does COption keep 4 bytes for only matching the appended tags, shouldn't it be enough in just 1 bit storage?
/// Mint data.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Mint {
/// Optional authority used to mint new tokens. The mint authority may only be provided during
/// mint creation. If no mint authority is present then the mint has a fixed supply and no
/// further tokens may be minted.
pub mint_authority: COption<Pubkey>,
/// Total supply of tokens.
pub supply: u64,
/// Number of base 10 digits to the right of the decimal place.
pub decimals: u8,
/// Is `true` if this structure has been initialized
pub is_initialized: bool,
/// Optional authority to freeze token accounts.
pub freeze_authority: COption<Pubkey>,
}
impl Pack for Mint {
const LEN: usize = 82;
fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError> {
let src = array_ref![src, 0, 82];
let (mint_authority, supply, decimals, is_initialized, freeze_authority) =
array_refs![src, 36, 8, 1, 1, 36];
...
}
...
fn pack_coption_u64(src: &COption<u64>, dst: &mut [u8; 12]) {
let (tag, body) = mut_array_refs![dst, 4, 8];
match src {
COption::Some(amount) => {
*tag = [1, 0, 0, 0];
*body = amount.to_le_bytes();
}
COption::None => {
*tag = [0; 4];
}
}
}
fn unpack_coption_u64(src: &[u8; 12]) -> Result<COption<u64>, ProgramError> {
let (tag, body) = array_refs![src, 4, 8];
match *tag {
[0, 0, 0, 0] => Ok(COption::None),
[1, 0, 0, 0] => Ok(COption::Some(u64::from_le_bytes(*body))),
_ => Err(ProgramError::InvalidAccountData),
}
}
Generally speaking, you are correct about repr(C) however; the rust documentation is your friend.
Regarding
COption
using 4 vs 1 byte to indicate presence or not. First consider the alignment benefits on memory addressing. Secondly, it does not presume any type of serialization (it is its own).