use crate::account::{read_layout_id, read_version, write_header, FixedLayout};
use crate::check::{check_owner, check_writable};
use hopper_runtime::{error::ProgramError, AccountView, Address, ProgramResult};
#[inline]
#[allow(clippy::too_many_arguments)]
pub fn migrate_append(
account: &AccountView,
payer: &AccountView,
program_id: &Address,
old_layout_id: &[u8; 8],
new_version: u8,
new_layout_id: &[u8; 8],
new_disc: u8,
new_size: usize,
) -> ProgramResult {
check_owner(account, program_id)?;
check_writable(account)?;
let data = account.try_borrow()?;
let current_layout = read_layout_id(&data)?;
if ¤t_layout != old_layout_id {
return Err(ProgramError::InvalidAccountData);
}
let current_version = read_version(&data)?;
if new_version <= current_version {
return Err(ProgramError::InvalidAccountData);
}
let old_size = data.len();
if new_size <= old_size {
return Err(ProgramError::InvalidArgument);
}
crate::account::safe_realloc(account, new_size, payer)?;
let mut data = account.try_borrow_mut()?;
write_header(&mut data, new_disc, new_version, new_layout_id)?;
for byte in &mut data[old_size..new_size] {
*byte = 0;
}
Ok(())
}
pub const fn is_append_compatible<Old: FixedLayout, New: FixedLayout>() -> bool {
New::SIZE > Old::SIZE
}
#[derive(Clone, Copy)]
pub struct MigrationDescriptor {
pub from_name: &'static str,
pub from_version: u8,
pub from_layout_id: [u8; 8],
pub to_name: &'static str,
pub to_version: u8,
pub to_layout_id: [u8; 8],
pub kind: MigrationKind,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum MigrationKind {
Append,
SegmentAppend,
Full,
}