#![allow(clippy::inline_always)]
use super::*;
#[inline(always)]
pub(crate) fn get_valid_buffer_capacity(
buffer_len: usize,
offset: usize,
) -> Result<usize, ProgramError> {
if offset == 0 {
if buffer_len == MAX_SIZE {
return Ok(MAX_ENTRIES);
}
if buffer_len < NUM_ENTRIES_SIZE {
return Err(ProgramError::AccountDataTooSmall);
}
let entry_data_len = buffer_len - NUM_ENTRIES_SIZE;
if !entry_data_len.is_multiple_of(ENTRY_SIZE) {
return Err(ProgramError::InvalidArgument);
}
Ok(entry_data_len / ENTRY_SIZE)
} else {
if !buffer_len.is_multiple_of(ENTRY_SIZE) {
return Err(ProgramError::InvalidArgument);
}
Ok(buffer_len / ENTRY_SIZE)
}
}
#[inline(always)]
pub fn validate_fetch_offset(offset: usize, buffer_len: usize) -> Result<(), ProgramError> {
if offset >= MAX_SIZE {
return Err(ProgramError::InvalidArgument);
}
if offset != 0
&& (offset < NUM_ENTRIES_SIZE || !(offset - NUM_ENTRIES_SIZE).is_multiple_of(ENTRY_SIZE))
{
return Err(ProgramError::InvalidArgument);
}
if offset.saturating_add(buffer_len) > MAX_SIZE {
return Err(ProgramError::InvalidArgument);
}
Ok(())
}
#[inline(always)]
pub fn fetch_into(buffer: &mut [u8], offset: usize) -> Result<usize, ProgramError> {
let num_entries = get_valid_buffer_capacity(buffer.len(), offset)?;
validate_fetch_offset(offset, buffer.len())?;
unsafe { fetch_into_unchecked(buffer, offset) }?;
if offset == 0 {
Ok(unsafe { get_entry_count(buffer) })
} else {
Ok(num_entries)
}
}
#[inline(always)]
pub unsafe fn fetch_into_unchecked(buffer: &mut [u8], offset: usize) -> Result<(), ProgramError> {
crate::sysvars::get_sysvar_unchecked(buffer.as_mut_ptr(), &SLOTHASHES_ID, offset, buffer.len())
}