Skip to main content

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<'a> Attribute<'a> {
12    pub fn name(&self) -> &'a str {
13        self.ctor().parent().name()
14    }
15
16    pub fn namespace(&self) -> &'a str {
17        self.ctor().parent().namespace()
18    }
19
20    pub fn parent(&self) -> HasAttribute<'a> {
21        self.decode(0)
22    }
23
24    pub fn ctor(&self) -> AttributeType<'a> {
25        self.decode(1)
26    }
27
28    pub fn value(&self) -> Vec<(String, Value)> {
29        let signature = self.ctor().signature(&[]);
30        debug_assert_eq!(signature.flags, MethodCallAttributes::HASTHIS);
31        debug_assert_eq!(signature.return_type, Type::Void);
32
33        let mut values = Vec::with_capacity(signature.types.len());
34        let mut blob = self.blob(2);
35        let prolog = blob.read_u16();
36        debug_assert_eq!(prolog, 1);
37
38        for ty in &signature.types {
39            let value = read_value(&mut blob, ty);
40            values.push((String::new(), value));
41        }
42
43        let named_arg_count = blob.read_u16();
44        values.reserve(named_arg_count as usize);
45
46        for _ in 0..named_arg_count {
47            let _id = blob.read_u8();
48            // Per ECMA-335 II.23.3, this byte is 0x53 (FIELD) or 0x54 (PROPERTY),
49            // indicating whether the named argument targets a field or a property.
50            let ty = blob.read_type_code(&[]);
51            let name = blob.read_utf8();
52            let value = read_value(&mut blob, &ty);
53            values.push((name, value));
54        }
55
56        debug_assert_eq!(blob.len(), 0);
57        values
58    }
59}
60
61fn read_value(blob: &mut Blob, ty: &Type) -> Value {
62    match ty {
63        Type::Bool => Value::Bool(blob.read_bool()),
64        Type::I8 => Value::I8(blob.read_i8()),
65        Type::U8 => Value::U8(blob.read_u8()),
66        Type::I16 => Value::I16(blob.read_i16()),
67        Type::U16 => Value::U16(blob.read_u16()),
68        Type::I32 => Value::I32(blob.read_i32()),
69        Type::U32 => Value::U32(blob.read_u32()),
70        Type::I64 => Value::I64(blob.read_i64()),
71        Type::U64 => Value::U64(blob.read_u64()),
72        Type::F32 => Value::F32(blob.read_f32()),
73        Type::F64 => Value::F64(blob.read_f64()),
74        Type::String => Value::Utf8(blob.read_utf8()),
75        Type::ClassName(tn) if tn == ("System", "Type") => {
76            let s = blob.read_utf8();
77            if let Some(dot) = s.rfind('.') {
78                Value::TypeName(TypeName::named(&s[..dot], &s[dot + 1..]))
79            } else {
80                Value::TypeName(TypeName::named("", &s))
81            }
82        }
83        Type::ValueName(tn) | Type::ClassName(tn) => {
84            Value::EnumValue(tn.clone(), Box::new(Value::I32(blob.read_i32())))
85        }
86        rest => panic!("{rest:?}"),
87    }
88}