pub struct ItemInformation<'s, I> { /* private fields */ }
Expand description

Zero-copy access to a PDB type or id stream.

PDBs store two kinds of related streams with an identical internal structure:

  • TypeInformation (TPI stream) contains information on primitive types, classes and procedures, including their return type and arguments. Its contents are identified by TypeIndex.
  • IdInformation (IPI stream) is a stricter version of the above stream that contains inline functions, build infos and source references. Its contents are identified by IdIndex.

Items in these streams are stored by their index in ascending order. Symbols declared in ModuleInfo can refer to items in both streams, as well as items to other items with one exception: Types cannot refer to Ids. Also, the PDB format requires that items refer only to types with lower indexes. Thus, the stream of items forms a directed acyclic graph.

Both streams can iterate by their index using ItemInformation::iter. Additionally, ItemFinder is a secondary data structure to provide efficient backtracking for random access.

There are type definitions for both streams:

Examples

Iterating over the types while building a TypeFinder:


let type_information = pdb.type_information()?;
let mut type_finder = type_information.finder();

let mut iter = type_information.iter();
while let Some(typ) = iter.next()? {
    // build the type finder as we go
    type_finder.update(&iter);

    // parse the type record
    match typ.parse() {
        Ok(pdb::TypeData::Class(pdb::ClassType {name, properties, fields: Some(fields), ..})) => {
            // this Type describes a class-like type with fields
            println!("type {} is a class named {}", typ.index(), name);

            // `fields` is a TypeIndex which refers to a FieldList
            // To find information about the fields, find and parse that Type
            match type_finder.find(fields)?.parse()? {
                pdb::TypeData::FieldList(list) => {
                    // `fields` is a Vec<TypeData>
                    for field in list.fields {
                        if let pdb::TypeData::Member(member) = field {
                            // follow `member.field_type` as desired
                            println!("  - field {} at offset {:x}", member.name, member.offset);
                        } else {
                            // handle member functions, nested types, etc.
                        }
                    }

                    if let Some(more_fields) = list.continuation {
                        // A FieldList can be split across multiple records
                        // TODO: follow `more_fields` and handle the next FieldList
                    }
                }
                _ => { }
            }

        },
        Ok(_) => {
            // ignore everything that's not a class-like type
        },
        Err(pdb::Error::UnimplementedTypeKind(_)) => {
            // found an unhandled type record
            // this probably isn't fatal in most use cases
        },
        Err(e) => {
            // other error, probably is worth failing
            return Err(e);
        }
    }
}

Implementations

Returns an iterator that can traverse the type table in sequential order.

Returns the number of items contained in this ItemInformation.

Note that in the case of the type stream (TypeInformation) primitive types are not stored in the PDB file. The number of distinct types reachable via this table will be higher than len().

Returns whether this ItemInformation contains any data.

Returns an ItemFinder with a default time-space tradeoff useful for access by ItemIndex.

The ItemFinder is initially empty and must be populated by iterating. See the struct-level docs for an example.

Trait Implementations

Formats the value using the given formatter. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.