use std::collections::HashMap;
use pdb::FallibleIterator;
fn setup<F>(func: F)
where
F: FnOnce(&pdb::TypeInformation<'_>),
{
let file = if let Ok(filename) = std::env::var("PDB_FILE") {
std::fs::File::open(filename)
} else {
std::fs::File::open("fixtures/self/foo.pdb")
}
.expect("opening file");
let mut pdb = pdb::PDB::open(file).expect("opening pdb");
let type_information = pdb.type_information().expect("type information");
func(&type_information);
}
#[test]
fn iteration() {
setup(|type_information| {
let len = type_information.len();
let mut count: usize = 0;
let mut last_index = pdb::TypeIndex(4095);
let mut iter = type_information.iter();
while let Some(typ) = iter.next().expect("next type") {
assert_eq!(typ.index().0, last_index.0 + 1);
last_index = typ.index();
count += 1;
}
assert_eq!(len, count);
});
}
#[test]
fn type_finder() {
setup(|type_information| {
let mut type_finder = type_information.finder();
let mut map: HashMap<pdb::TypeIndex, pdb::Type<'_>> = HashMap::new();
assert_eq!(type_finder.max_index().0 >> 3, 4096 >> 3);
let mut iter = type_information.iter();
while let Some(typ) = iter.next().expect("next type") {
assert_eq!(type_finder.max_index().0 >> 3, typ.index().0 >> 3);
type_finder.update(&iter);
map.insert(typ.index(), typ);
}
for (index, typ) in map.iter() {
let found = type_finder.find(*index).expect("find");
assert_eq!(*typ, found);
}
})
}
#[test]
fn find_classes() {
setup(|type_information| {
let mut type_finder = type_information.finder();
let mut iter = type_information.iter();
while let Some(typ) = iter.next().expect("next type") {
type_finder.update(&iter);
match typ.parse() {
Ok(pdb::TypeData::Class(pdb::ClassType {
name,
fields: Some(fields),
..
})) => {
println!("class {} (type {}):", name, typ.index());
match type_finder.find(fields).expect("find fields").parse() {
Ok(pdb::TypeData::FieldList(list)) => {
for field in list.fields {
println!(" - {:?}", field);
}
if let Some(c) = list.continuation {
println!("TODO: follow to type {}", c);
}
}
Ok(value) => {
panic!("expected a field list, got {:?}", value);
}
Err(e) => {
println!("field parse error: {}", e);
}
}
}
Ok(pdb::TypeData::Enumeration(data)) => {
println!("enum {} (type {}):", data.name, data.fields);
match type_finder.find(data.fields).expect("find fields").parse() {
Ok(pdb::TypeData::FieldList(list)) => {
for field in list.fields {
println!(" - {:?}", field);
}
if let Some(c) = list.continuation {
println!("TODO: follow to type {}", c);
}
}
Ok(value) => {
panic!("expected a field list, got {:?}", value);
}
Err(e) => {
println!("field parse error: {}", e);
}
}
}
Ok(pdb::TypeData::FieldList(_)) => {
}
Ok(_) => {
}
Err(pdb::Error::UnimplementedTypeKind(kind)) => {
println!("unimplemented: 0x{:04x}", kind);
}
Err(e) => {
println!(
"other parse error on type {} (raw type {:04x}): {}",
typ.index(),
typ.raw_kind(),
e
);
panic!("dying due to parse error");
}
}
}
})
}