use 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 fn parse(buf: &mut ParseBuffer) -> Result<Header> {
assert!(buf.pos() == 0);
let h = 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 h.header_size < bytes_read {
return Err(Error::InvalidTypeInformationHeader("header size is impossibly small"));
} else if h.header_size > 1024 {
return Err(Error::InvalidTypeInformationHeader("header size is unreasonably large"));
}
buf.take((h.header_size - bytes_read) as usize)?;
if h.minimum_type_index < 4096 {
return Err(Error::InvalidTypeInformationHeader("minimum type index is < 4096"));
}
if h.maximum_type_index < h.minimum_type_index {
return Err(Error::InvalidTypeInformationHeader("maximum type index is < minimum type index"));
}
Ok(h)
}
}