use crate::ko::errors::ReldSectionParseError;
use crate::ko::symbols::ReldEntry;
use crate::ko::SectionIdx;
use crate::{BufferIterator, WritableBuffer};
use std::slice::Iter;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ReldIdx(usize);
impl From<usize> for ReldIdx {
fn from(i: usize) -> Self {
Self(i)
}
}
impl From<u8> for ReldIdx {
fn from(i: u8) -> Self {
Self(i as usize)
}
}
impl From<u16> for ReldIdx {
fn from(i: u16) -> Self {
Self(i as usize)
}
}
impl From<u32> for ReldIdx {
fn from(i: u32) -> Self {
Self(i as usize)
}
}
impl From<ReldIdx> for usize {
fn from(reld_idx: ReldIdx) -> Self {
reld_idx.0
}
}
#[derive(Debug)]
pub struct ReldSection {
entries: Vec<ReldEntry>,
size: u32,
section_index: SectionIdx,
}
impl ReldSection {
pub fn new(section_index: SectionIdx) -> Self {
Self {
entries: Vec::new(),
size: 0,
section_index,
}
}
pub fn with_capacity(amount: usize, section_index: SectionIdx) -> Self {
Self {
entries: Vec::with_capacity(amount),
size: 0,
section_index,
}
}
pub fn add(&mut self, entry: ReldEntry) -> ReldIdx {
self.size += entry.size_bytes();
self.entries.push(entry);
ReldIdx::from(self.entries.len() - 1)
}
pub fn get(&self, index: ReldIdx) -> Option<&ReldEntry> {
self.entries.get(usize::from(index))
}
pub fn entries(&self) -> Iter<ReldEntry> {
self.entries.iter()
}
pub fn size(&self) -> u32 {
self.size
}
pub fn section_index(&self) -> SectionIdx {
self.section_index
}
pub fn parse(
source: &mut BufferIterator,
size: u32,
section_index: SectionIdx,
) -> Result<Self, ReldSectionParseError> {
let mut bytes_read = 0;
let mut entries = Vec::new();
while bytes_read < size {
let entry = ReldEntry::parse(source).map_err(|e| {
ReldSectionParseError::ReldEntryParseError(entries.len(), source.current_index(), e)
})?;
bytes_read += entry.size_bytes();
entries.push(entry);
}
Ok(Self {
entries,
size,
section_index,
})
}
pub fn write(&self, buf: &mut impl WritableBuffer) {
for reld_entry in self.entries.iter() {
reld_entry.write(buf);
}
}
}