use crate::{
Error,
util::{read_i16_le, read_i32_le, read_u32_le},
};
#[derive(Clone, Copy, Debug)]
pub struct VarRecord<'a> {
bytes: &'a [u8],
}
impl<'a> VarRecord<'a> {
pub(crate) fn new(bytes: &'a [u8]) -> Self {
Self { bytes }
}
pub const BASE_SIZE: usize = 0x14;
pub fn from_raw(bytes: &'a [u8]) -> Result<Self, Error> {
if bytes.len() < Self::BASE_SIZE {
return Err(Error::TooShort {
expected: Self::BASE_SIZE,
actual: bytes.len(),
context: "VarRecord",
});
}
Ok(VarRecord { bytes })
}
#[inline]
pub fn as_bytes(&self) -> &'a [u8] {
self.bytes
}
#[inline]
pub fn info(&self) -> u32 {
read_u32_le(self.bytes, 0x00).unwrap_or(0)
}
#[inline]
pub fn record_size(&self) -> usize {
(self.info() & 0xFFFF) as usize
}
#[inline]
pub fn datatype(&self) -> i32 {
read_i32_le(self.bytes, 0x04).unwrap_or(-1)
}
#[inline]
pub fn flags(&self) -> u32 {
read_u32_le(self.bytes, 0x08).unwrap_or(0)
}
#[inline]
pub fn varkind(&self) -> i16 {
read_i16_le(self.bytes, 0x0C).unwrap_or(0)
}
#[inline]
pub fn vardesc_size(&self) -> i16 {
read_i16_le(self.bytes, 0x0E).unwrap_or(0)
}
#[inline]
pub fn offs_value(&self) -> i32 {
read_i32_le(self.bytes, 0x10).unwrap_or(0)
}
fn nrattribs(&self) -> usize {
self.record_size().saturating_sub(Self::BASE_SIZE) / 4
}
pub fn help_context(&self) -> Option<i32> {
if self.nrattribs() > 0 {
read_i32_le(self.bytes, 0x14)
} else {
None
}
}
pub fn help_string_offset(&self) -> Option<i32> {
if self.nrattribs() > 1 {
read_i32_le(self.bytes, 0x18)
} else {
None
}
}
pub fn res9(&self) -> Option<i32> {
if self.nrattribs() > 2 {
read_i32_le(self.bytes, 0x1C)
} else {
None
}
}
pub fn cust_data_offset(&self) -> Option<i32> {
if self.nrattribs() > 3 {
read_i32_le(self.bytes, 0x20)
} else {
None
}
}
pub fn helpstringcontext(&self) -> Option<i32> {
if self.nrattribs() > 4 {
read_i32_le(self.bytes, 0x24)
} else {
None
}
}
}