use std::fmt;
use std::result;
use crate::common::*;
use crate::msf::Stream;
use crate::FallibleIterator;
pub(crate) mod constants;
mod data;
mod header;
mod primitive;
use self::data::parse_type_data;
use self::header::*;
use self::primitive::type_data_for_primitive;
pub use self::data::*;
pub use self::primitive::{Indirection, PrimitiveKind, PrimitiveType};
#[derive(Debug)]
pub struct TypeInformation<'s> {
stream: Stream<'s>,
header: Header,
}
impl<'s> TypeInformation<'s> {
pub(crate) fn parse(stream: Stream<'s>) -> Result<Self> {
let mut buf = stream.parse_buffer();
let header = Header::parse(&mut buf)?;
Ok(TypeInformation { stream, header })
}
pub fn iter(&self) -> TypeIter<'_> {
let mut buf = self.stream.parse_buffer();
buf.take(self.header.header_size as usize)
.expect("dropping TPI header");
TypeIter {
buf,
type_index: self.header.minimum_type_index,
}
}
pub fn len(&self) -> usize {
(self.header.maximum_type_index - self.header.minimum_type_index) as usize
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn type_finder(&self) -> TypeFinder<'_> {
TypeFinder::new(self, 3)
}
#[doc(hidden)]
#[deprecated(note = "use type_finder() instead")]
pub fn new_type_finder(&self) -> TypeFinder<'_> {
self.type_finder()
}
}
const PRIMITIVE_TYPE: &[u8] = b"\xff\xff";
#[derive(Copy, Clone, PartialEq)]
pub struct Type<'t>(TypeIndex, &'t [u8]);
impl<'t> Type<'t> {
pub fn type_index(&self) -> TypeIndex {
self.0
}
pub fn len(&self) -> usize {
self.1.len()
}
pub fn is_empty(&self) -> bool {
self.1.is_empty()
}
#[inline]
pub fn raw_kind(&self) -> u16 {
debug_assert!(self.1.len() >= 2);
u16::from(self.1[0]) | (u16::from(self.1[1]) << 8)
}
pub fn parse(&self) -> Result<TypeData<'t>> {
if self.0 < 0x1000 {
type_data_for_primitive(self.0)
} else {
let mut buf = ParseBuffer::from(self.1);
parse_type_data(&mut buf)
}
}
}
impl<'t> fmt::Debug for Type<'t> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Type{{ kind: 0x{:4x} [{} bytes] }}",
self.raw_kind(),
self.1.len()
)
}
}
#[derive(Debug)]
pub struct TypeFinder<'t> {
buffer: ParseBuffer<'t>,
minimum_type_index: TypeIndex,
maximum_type_index: TypeIndex,
positions: Vec<u32>,
shift: u8,
}
impl<'t> TypeFinder<'t> {
fn new(type_info: &'t TypeInformation<'_>, shift: u8) -> Self {
let count = type_info.header.maximum_type_index - type_info.header.minimum_type_index;
let shifted_count = (count >> shift) as usize;
let mut positions = Vec::with_capacity(shifted_count);
positions.push(type_info.header.header_size);
TypeFinder {
buffer: type_info.stream.parse_buffer(),
minimum_type_index: type_info.header.minimum_type_index,
maximum_type_index: type_info.header.maximum_type_index,
positions,
shift,
}
}
#[inline]
fn resolve(&self, type_index: TypeIndex) -> (usize, usize) {
let raw = type_index - self.minimum_type_index;
(
(raw >> self.shift) as usize,
(raw & ((1 << self.shift) - 1)) as usize,
)
}
#[inline]
pub fn max_indexed_type(&self) -> TypeIndex {
(self.positions.len() << self.shift) as TypeIndex + self.minimum_type_index - 1
}
#[inline]
pub fn update(&mut self, iterator: &TypeIter<'_>) {
let (vec_index, iteration_count) = self.resolve(iterator.type_index);
if iteration_count == 0 && vec_index == self.positions.len() {
let pos = iterator.buf.pos();
assert!(pos < u32::max_value() as usize);
self.positions.push(pos as u32);
}
}
pub fn find(&self, type_index: TypeIndex) -> Result<Type<'t>> {
if type_index < self.minimum_type_index {
return Ok(Type(type_index, PRIMITIVE_TYPE));
} else if type_index > self.maximum_type_index {
return Err(Error::TypeNotFound(type_index));
}
let (vec_index, iteration_count) = self.resolve(type_index);
if let Some(pos) = self.positions.get(vec_index) {
let mut buf = self.buffer.clone();
buf.take(*pos as usize)?;
for _ in 0..iteration_count {
let length = buf.parse_u16()?;
buf.take(length as usize)?;
}
let length = buf.parse_u16()?;
Ok(Type(type_index, buf.take(length as usize)?))
} else {
Err(Error::TypeNotIndexed(type_index, self.max_indexed_type()))
}
}
}
#[derive(Debug)]
pub struct TypeIter<'t> {
buf: ParseBuffer<'t>,
type_index: TypeIndex,
}
impl<'t> FallibleIterator for TypeIter<'t> {
type Item = Type<'t>;
type Error = Error;
fn next(&mut self) -> result::Result<Option<Self::Item>, Self::Error> {
if self.buf.is_empty() {
return Ok(None);
}
let length = self.buf.parse_u16()? as usize;
if length < 2 {
return Err(Error::TypeTooShort);
}
let type_buf = self.buf.take(length)?;
let my_type_index = self.type_index;
self.type_index += 1;
Ok(Some(Type(my_type_index, type_buf)))
}
}