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}