use crate::common::*;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Slice {
pub offset: i32, pub size: u32,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Header {
pub version: u32,
pub header_size: u32,
pub minimum_type_index: TypeIndex,
pub maximum_type_index: TypeIndex,
pub gprec_size: u32,
pub tpi_hash_stream: u16,
pub tpi_hash_pad_stream: u16,
pub hash_key_size: u32,
pub hash_bucket_size: u32,
pub hash_values: Slice,
pub ti_off: Slice,
pub hash_adj: Slice, }
impl Header {
pub(crate) fn parse(buf: &mut ParseBuffer<'_>) -> Result<Self> {
assert!(buf.pos() == 0);
let header = Header {
version: buf.parse_u32()?,
header_size: buf.parse_u32()?,
minimum_type_index: buf.parse_u32()?,
maximum_type_index: buf.parse_u32()?,
gprec_size: buf.parse_u32()?,
tpi_hash_stream: buf.parse_u16()?,
tpi_hash_pad_stream: buf.parse_u16()?,
hash_key_size: buf.parse_u32()?,
hash_bucket_size: buf.parse_u32()?,
hash_values: Slice {
offset: buf.parse_i32()?,
size: buf.parse_u32()?,
},
ti_off: Slice {
offset: buf.parse_i32()?,
size: buf.parse_u32()?,
},
hash_adj: Slice {
offset: buf.parse_i32()?,
size: buf.parse_u32()?,
},
};
let bytes_read = buf.pos() as u32;
if header.header_size < bytes_read {
return Err(Error::InvalidTypeInformationHeader(
"header size is impossibly small",
));
} else if header.header_size > 1024 {
return Err(Error::InvalidTypeInformationHeader(
"header size is unreasonably large",
));
}
buf.take((header.header_size - bytes_read) as usize)?;
if header.minimum_type_index < 4096 {
return Err(Error::InvalidTypeInformationHeader(
"minimum type index is < 4096",
));
}
if header.maximum_type_index < header.minimum_type_index {
return Err(Error::InvalidTypeInformationHeader(
"maximum type index is < minimum type index",
));
}
Ok(header)
}
}