windows_metadata/reader/tables/
attribute.rs

1use super::*;
2
3impl std::fmt::Debug for Attribute<'_> {
4    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5        f.debug_tuple("Attribute")
6            .field(&self.ctor().parent().name())
7            .finish()
8    }
9}
10
11impl Attribute<'_> {
12    pub fn parent(&self) -> HasAttribute {
13        self.decode(0)
14    }
15
16    pub fn ctor(&self) -> AttributeType {
17        self.decode(1)
18    }
19
20    pub fn value(&self) -> Vec<(String, Value)> {
21        let signature = self.ctor().signature(&[]);
22        debug_assert_eq!(signature.flags, MethodCallAttributes::HASTHIS);
23        debug_assert_eq!(signature.return_type, Type::Void);
24
25        let mut values = Vec::with_capacity(signature.types.len());
26        let mut blob = self.blob(2);
27        let prolog = blob.read_u16();
28        debug_assert_eq!(prolog, 1);
29
30        for ty in &signature.types {
31            let mut name = String::new();
32            let value = read_value(&mut blob, ty, &mut name);
33            debug_assert!(name.is_empty());
34            values.push((name, value));
35        }
36
37        let named_arg_count = blob.read_u16();
38        values.reserve(named_arg_count as usize);
39
40        for _ in 0..named_arg_count {
41            let _id = blob.read_u8();
42            // TODO: what's ID?
43            let ty = blob.read_type_code(&[]);
44            let mut name = blob.read_utf8();
45            let value = read_value(&mut blob, &ty, &mut name);
46            values.push((name, value));
47        }
48
49        debug_assert_eq!(blob.len(), 0);
50        values
51    }
52}
53
54fn read_value(blob: &mut Blob, ty: &Type, name: &mut String) -> Value {
55    match ty {
56        Type::Bool => Value::Bool(blob.read_bool()),
57        Type::I8 => Value::I8(blob.read_i8()),
58        Type::U8 => Value::U8(blob.read_u8()),
59        Type::I16 => Value::I16(blob.read_i16()),
60        Type::U16 => Value::U16(blob.read_u16()),
61        Type::I32 => Value::I32(blob.read_i32()),
62        Type::U32 => Value::U32(blob.read_u32()),
63        Type::I64 => Value::I64(blob.read_i64()),
64        Type::U64 => Value::U64(blob.read_u64()),
65        Type::String => Value::Utf8(blob.read_utf8()),
66        Type::Name(tn) => {
67            if tn.namespace == "System" && tn.name == "Type" {
68                Value::Utf8(blob.read_utf8())
69            } else {
70                Value::I32(blob.read_i32())
71            }
72        }
73        Type::AttributeEnum => {
74            let enum_name = name.clone();
75            *name = blob.read_utf8();
76            Value::AttributeEnum(enum_name, blob.read_i32())
77        }
78        rest => panic!("{rest:?}"),
79    }
80}