use std::cmp::max;
use std::io::{Read, Write, Result};
use byteorder::{LE, ReadBytesExt, WriteBytesExt};
pub use crate::sig::*;
pub use crate::ver::*;
#[derive(Debug, Default)]
pub struct Section {
pub offset: u32,
pub count: u32,
}
impl Section {
#[inline]
pub fn read<R: Read>(reader: &mut R) -> Result<Self> {
Ok(Section {
offset: reader.read_u32::<LE>()?,
count: reader.read_u32::<LE>()?,
})
}
#[inline]
pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
writer.write_u32::<LE>(self.offset)?;
writer.write_u32::<LE>(self.count)
}
}
#[derive(Debug)]
pub struct Header {
pub signature: Signature,
pub version: Version,
pub structs: Section,
pub fields: Section,
pub labels: Section,
pub field_data: Section,
pub field_indices: Section,
pub list_indices: Section,
}
impl Header {
#[inline]
pub fn new(signature: Signature) -> Self {
Self::with_version(signature, Version::V3_2)
}
#[inline]
pub fn with_version(signature: Signature, version: Version) -> Self {
Header {
signature,
version,
structs: Section::default(),
fields: Section::default(),
labels: Section::default(),
field_data: Section::default(),
field_indices: Section::default(),
list_indices: Section::default(),
}
}
pub fn read<R: Read>(reader: &mut R) -> Result<Self> {
Ok(Header {
signature: Signature::read(reader)?,
version: Version::read(reader)?,
structs: Section::read(reader)?,
fields: Section::read(reader)?,
labels: Section::read(reader)?,
field_data: Section::read(reader)?,
field_indices: Section::read(reader)?,
list_indices: Section::read(reader)?,
})
}
pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
self.signature.write(writer)?;
self.version.write(writer)?;
self.structs.write(writer)?;
self.fields.write(writer)?;
self.labels.write(writer)?;
self.field_data.write(writer)?;
self.field_indices.write(writer)?;
self.list_indices.write(writer)
}
#[inline]
pub fn token_count(&self) -> usize {
let size = (self.structs.count + self.list_indices.count)*2;
max(size, self.fields.count) as usize
}
}