use crate::{HEADER_SIZE, Result, Error, SECTION_SIZE};
use core::ops::Index;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SectionError {
LengthError,
BaseError(u32),
EntryOffsetOutOfRange(u32, u32),
}
#[repr(C, packed)]
#[derive(Debug, Clone, Copy)]
pub struct Section {
pub name: [u8; 16],
pub is_loadable: bool,
pub is_execable: bool,
pub base: u32,
pub length: u32,
pub _reserved: [u8; 6],
}
impl Section {
#[inline]
pub const fn to_array(&self) -> [u8; SECTION_SIZE] {
unsafe { core::ptr::read(self as *const Self as *const [u8; SECTION_SIZE]) }
}
#[inline]
pub fn validate(&self) -> Result<()> {
if self.length == 0 {
return Err(Error::SectionError(SectionError::LengthError));
}
if self.base as usize >= (HEADER_SIZE + SECTION_SIZE) {
return Err(Error::SectionError(SectionError::BaseError(self.base)));
}
Ok(())
}
}
#[derive(Debug, Clone, Copy)]
pub struct SectionIter<'a> {
buf: &'a [u8],
total: u16,
current: u16,
}
impl<'a> SectionIter<'a> {
pub(crate) fn new(buf: &'a [u8], total: u16, current: u16) -> Self {
Self {
buf,
total,
current,
}
}
}
impl<'a> Iterator for SectionIter<'a> {
type Item = Section;
fn next(&mut self) -> Option<Self::Item> {
if self.current >= self.total {
return None;
}
let base = HEADER_SIZE + self.current as usize * SECTION_SIZE;
let buf = &self.buf[base..base + SECTION_SIZE];
let section = unsafe { *(buf.as_ptr() as *const Section) };
self.current += 1;
Some(section)
}
}
impl Index<usize> for SectionIter<'_> {
type Output = Section;
fn index(&self, index: usize) -> &Self::Output {
if index >= self.total as usize {
panic!(
"proka-exec: index out of bounds, the max size is {}, but index {} was got.",
self.total, index
)
}
let base = HEADER_SIZE;
let target = base + index * SECTION_SIZE;
let buf = &self.buf[target..target + SECTION_SIZE];
unsafe { &*(buf.as_ptr() as *const Section) }
}
}