Skip to main content

msft_typelib/
custdata.rs

1//! [`CustDataEntry`] -- custom data GUID directory (segment 12).
2//!
3//! COM type libraries can attach arbitrary named attributes (custom data)
4//! to the library, each TypeInfo, each function, each parameter, and each
5//! variable.  These attributes are identified by GUID and carry a variant
6//! value stored in the custom-data table (segment 11).
7//!
8//! The CDGuids directory (segment 12) is a set of 12-byte entries that
9//! form hash-chained linked lists.  Given an `oCustData` offset (from
10//! the header, a TypeInfo, or a record attribute), you walk the chain
11//! via [`CustDataEntry::next`] until it returns `-1`.
12//!
13//! Use [`TypeLib::resolve_cust_data_entry`](crate::TypeLib::resolve_cust_data_entry)
14//! to decode each entry into a `(Guid, ConstValue)` pair.
15
16use crate::util::read_i32_le;
17
18/// One entry in the CDGuids directory (12 bytes).
19///
20/// Each entry links a GUID to a custom data value and forms a
21/// linked list via the [`next`](Self::next) field.
22#[derive(Clone, Copy, Debug)]
23pub struct CustDataEntry<'a> {
24    bytes: &'a [u8],
25}
26
27impl<'a> CustDataEntry<'a> {
28    /// Wraps a 12-byte slice as a `CustDataEntry`.
29    pub(crate) fn new(bytes: &'a [u8]) -> Self {
30        Self { bytes }
31    }
32
33    /// Size of one CDGuids entry in bytes.
34    pub const SIZE: usize = 12;
35
36    /// Offset into the GUID table for the attribute's GUID.
37    #[inline]
38    pub fn guid_offset(&self) -> i32 {
39        read_i32_le(self.bytes, 0x00).unwrap_or(-1)
40    }
41
42    /// Offset into the custom data segment (segment 11) for the value.
43    #[inline]
44    pub fn data_offset(&self) -> i32 {
45        read_i32_le(self.bytes, 0x04).unwrap_or(-1)
46    }
47
48    /// Offset of the next entry in the chain, or `-1` if last.
49    #[inline]
50    pub fn next(&self) -> i32 {
51        read_i32_le(self.bytes, 0x08).unwrap_or(-1)
52    }
53}