use common::*;
use msf::*;
use uuid::Uuid;
use dbi::HeaderVersion;
use std::mem;
#[derive(Debug)]
pub struct PDBInformation<'s> {
pub version: HeaderVersion,
pub signature: u32,
pub age: u32,
pub guid: Uuid,
pub names_offset: usize,
pub names_size: usize,
stream: Stream<'s>,
}
impl<'s> PDBInformation<'s> {
pub fn stream_names(&self) -> Result<StreamNames> {
parse_names(self)
}
}
#[derive(Debug)]
pub struct StreamName<'n> {
pub name: RawString<'n>,
pub stream_id: u32,
}
#[derive(Debug)]
pub struct StreamNames<'s> {
buf: ParseBuffer<'s>,
names: Vec<StreamName<'s>>,
}
pub type NameIter<'a, 'n> = ::std::slice::Iter<'a, StreamName<'n>>;
impl<'s> StreamNames<'s> {
pub fn iter<'a>(&'a self) -> NameIter<'a,'s> {
self.names.iter()
}
}
fn parse_names<'b, 's: 'b>(info: &'b PDBInformation<'s>) -> Result<StreamNames<'b>> {
let mut names = vec![];
let buf = {
let mut buf = info.stream.parse_buffer();
buf.take(info.names_offset + info.names_size)?;
let count = buf.parse_u32()?;
let _entries_size = buf.parse_u32()?;
let ok_words = buf.parse_u32()?;
let _ok_bits = buf.take(ok_words as usize * mem::size_of::<u32>())?;
let deleted_words = buf.parse_u32()?;
let _deleted_bits = buf.take(deleted_words as usize * mem::size_of::<u32>())?;
let mut names_reader = info.stream.parse_buffer();
names_reader.take(info.names_offset)?;
let names_buf = names_reader.take(info.names_size)?;
for _ in 0..count {
let name_offset = buf.parse_u32()? as usize;
let stream_id = buf.parse_u32()?;
let name = ParseBuffer::from(&names_buf[name_offset..]).parse_cstring()?;
names.push(StreamName {
name,
stream_id,
});
}
names_reader
};
Ok(StreamNames {
buf,
names,
})
}
pub fn new_pdb_information(stream: Stream) -> Result<PDBInformation> {
let (version, signature, age, guid, names_size, names_offset) = {
let mut buf = stream.parse_buffer();
let version = From::from(buf.parse_u32()?);
let signature = buf.parse_u32()?;
let age = buf.parse_u32()?;
let guid = Uuid::from_fields(
buf.parse_u32()?,
buf.parse_u16()?,
buf.parse_u16()?,
buf.take(8)?
).unwrap();
let names_size = buf.parse_u32()? as usize;
let names_offset = buf.pos();
(version, signature, age, guid, names_size, names_offset)
};
Ok(PDBInformation {
version,
signature,
age,
guid,
names_size,
names_offset,
stream,
})
}