use solana_program::program_memory::sol_memcpy;
use super::*;
#[repr(C)]
#[cfg_attr(feature = "serde-feature", derive(Serialize, Deserialize))]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone, ShankAccount)]
pub struct EditionMarkerV2 {
pub key: Key,
pub ledger: Vec<u8>,
}
impl Default for EditionMarkerV2 {
fn default() -> Self {
Self {
key: Key::EditionMarkerV2,
ledger: vec![],
}
}
}
impl TokenMetadataAccount for EditionMarkerV2 {
fn key() -> Key {
Key::EditionMarkerV2
}
fn size() -> usize {
0
}
}
impl EditionMarkerV2 {
fn get_index(offset_from_start: usize) -> Result<usize, ProgramError> {
let index = offset_from_start
.checked_div(8)
.ok_or(MetadataError::NumericalOverflowError)?;
Ok(index)
}
fn get_offset_from_right(offset_from_start: usize) -> Result<u32, ProgramError> {
Ok(7 - offset_from_start
.checked_rem(8)
.ok_or(MetadataError::NumericalOverflowError)? as u32)
}
pub fn get_index_and_mask(edition: u64) -> Result<(usize, u8), ProgramError> {
let edition = edition
.try_into()
.map_err(|_| MetadataError::NumericalOverflowError)?;
let index = EditionMarkerV2::get_index(edition)?;
let my_position_in_index_starting_from_right =
EditionMarkerV2::get_offset_from_right(edition)?;
Ok((index, 1u8 << my_position_in_index_starting_from_right))
}
pub fn edition_taken(&self, edition: u64) -> Result<bool, ProgramError> {
let (index, mask) = EditionMarkerV2::get_index_and_mask(edition)?;
if self.ledger.len() <= index {
Ok(false)
} else {
let applied_mask = self.ledger[index] & mask;
Ok(applied_mask != 0)
}
}
pub fn insert_edition(&mut self, edition: u64) -> ProgramResult {
let (index, mask) = EditionMarkerV2::get_index_and_mask(edition)?;
if self.ledger.len() <= index {
self.ledger.resize(index + 1, 0);
}
self.ledger[index] |= mask;
Ok(())
}
pub fn save<'a>(
self,
account_info: &AccountInfo<'a>,
payer_info: &AccountInfo<'a>,
system_info: &AccountInfo<'a>,
) -> ProgramResult {
let serialized_data = self
.try_to_vec()
.map_err(|_| MetadataError::BorshSerializationError)?;
resize_or_reallocate_account_raw(
account_info,
payer_info,
system_info,
serialized_data.len(),
)?;
sol_memcpy(
&mut account_info.try_borrow_mut_data()?,
&serialized_data,
serialized_data.len(),
);
Ok(())
}
}