use crate::errors::FileParseError;
use crate::field::{ByteOrder, Field};
pub struct NoteEntry {
pub n_namesz: Field<u32>,
pub n_descsz: Field<u32>,
pub n_type: Field<u32>,
pub name: Vec<u8>,
pub desc: Vec<u8>,
}
impl NoteEntry {
pub fn name_string(&self) -> String {
let end = self
.name
.iter()
.position(|&b| b == 0)
.unwrap_or(self.name.len());
String::from_utf8_lossy(&self.name[..end]).into_owned()
}
}
pub struct NoteTable {
pub entries: Vec<NoteEntry>,
}
impl NoteTable {
pub fn parse(
buffer: &[u8],
offset: usize,
size: usize,
order: ByteOrder,
) -> Result<Self, FileParseError> {
let end = offset
.checked_add(size)
.ok_or(FileParseError::BufferOverflow)?;
let mut cursor = offset;
let mut entries = Vec::new();
while cursor + 12 <= end {
let n_namesz = Field::new(order.read_u32(buffer, cursor)?, cursor, 4);
let n_descsz = Field::new(order.read_u32(buffer, cursor + 4)?, cursor + 4, 4);
let n_type = Field::new(order.read_u32(buffer, cursor + 8)?, cursor + 8, 4);
cursor += 12;
let name_end = cursor
.checked_add(n_namesz.value as usize)
.ok_or(FileParseError::BufferOverflow)?;
let name = buffer
.get(cursor..name_end)
.ok_or(FileParseError::BufferOverflow)?
.to_vec();
cursor = align4(name_end);
let desc_end = cursor
.checked_add(n_descsz.value as usize)
.ok_or(FileParseError::BufferOverflow)?;
let desc = buffer
.get(cursor..desc_end)
.ok_or(FileParseError::BufferOverflow)?
.to_vec();
cursor = align4(desc_end);
entries.push(NoteEntry {
n_namesz,
n_descsz,
n_type,
name,
desc,
});
}
Ok(Self { entries })
}
}
fn align4(value: usize) -> usize {
(value + 3) & !3
}