use std::ops::Add;
use crate::header::Header;
pub trait Index {
fn offset(&self, header: &Header) -> u64;
}
macro_rules! index {
($(#[$attrs:meta])* $name:ident, $field:ident) => (
$(#[$attrs])*
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct $name(pub(crate) u32, pub(crate) u32);
impl Index for $name {
#[inline]
fn offset(&self, header: &Header) -> u64 {
let start = header.$field.offset as u64;
let offset = self.0 as u64 + self.1 as u64 * 4;
start + offset
}
}
impl Add<u32> for $name {
type Output = Self;
fn add(self, rhs: u32) -> Self {
$name(self.0, self.1 + rhs)
}
}
);
($(#[$attrs:meta])* $name:ident, $field:ident, $multiplier:expr) => (
$(#[$attrs])*
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct $name(pub(crate) u32);
impl Index for $name {
#[inline]
fn offset(&self, header: &Header) -> u64 {
let start = header.$field.offset as u64;
let offset = self.0 as u64 * $multiplier;
start + offset
}
}
impl From<u32> for $name {
fn from(value: u32) -> Self { $name(value) }
}
);
}
index!(
StructIndex, structs, 3*4
);
index!(
FieldIndex, fields, 3*4
);
index!(
LabelIndex, labels, 16
);
index!(
FieldIndicesIndex, field_indices
);
index!(
ListIndicesIndex, list_indices
);
index!(
U64Index, field_data, 1
);
index!(
I64Index, field_data, 1
);
index!(
F64Index, field_data, 1
);
index!(
StringIndex, field_data, 1
);
index!(
ResRefIndex, field_data, 1
);
index!(
LocStringIndex, field_data, 1
);
index!(
BinaryIndex, field_data, 1
);