Skip to main content

windows_metadata/reader/tables/
method_param.rs

1use super::*;
2
3/// Direction flags stored on an ECMA-335 `Param` row.
4#[derive(Copy, Clone, Debug, PartialEq, Eq)]
5pub enum ParamDirection {
6    Unspecified,
7    Input,
8    Output,
9    InputOutput,
10}
11
12/// A raw buffer-size relationship stored on a parameter attribute.
13///
14/// Values remain signed because validation against a method signature is projection policy.
15#[derive(Copy, Clone, Debug, PartialEq, Eq)]
16pub enum BufferRelationship {
17    ElementsParam(i16),
18    BytesParam(i16),
19    ElementsConst(i32),
20}
21
22impl std::fmt::Debug for MethodParam<'_> {
23    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
24        f.debug_tuple("MethodParam").field(&self.name()).finish()
25    }
26}
27
28impl MethodParam<'_> {
29    pub fn flags(&self) -> ParamAttributes {
30        ParamAttributes(self.usize(0).try_into().unwrap())
31    }
32
33    /// Returns the direction represented by the `In` and `Out` flags without applying type or
34    /// projection defaults.
35    pub fn direction(&self) -> ParamDirection {
36        let flags = self.flags();
37        match (
38            flags.contains(ParamAttributes::In),
39            flags.contains(ParamAttributes::Out),
40        ) {
41            (false, false) => ParamDirection::Unspecified,
42            (true, false) => ParamDirection::Input,
43            (false, true) => ParamDirection::Output,
44            (true, true) => ParamDirection::InputOutput,
45        }
46    }
47
48    /// Returns whether the ECMA-335 `Optional` flag is present.
49    pub fn is_optional(&self) -> bool {
50        self.flags().contains(ParamAttributes::Optional)
51    }
52
53    /// Returns whether `ReservedAttribute` is present.
54    pub fn is_reserved(&self) -> bool {
55        self.has_attribute("ReservedAttribute")
56    }
57
58    /// Returns whether `RetValAttribute` is present.
59    pub fn is_retval_attribute(&self) -> bool {
60        self.has_attribute("RetValAttribute")
61    }
62
63    /// Returns the raw count or byte-size relationship encoded by Win32 metadata attributes.
64    ///
65    /// This only decodes the attribute. Consumers remain responsible for validating signed values,
66    /// parameter positions, element sizes, and whether a public slice or span is appropriate.
67    pub fn buffer_relationship(&self) -> Option<BufferRelationship> {
68        let mut result = None;
69
70        for attribute in self.attributes() {
71            for (name, value) in attribute.value() {
72                let relationship = match (attribute.name(), name.as_str(), value) {
73                    ("NativeArrayInfoAttribute", "CountParamIndex", Value::I16(value)) => {
74                        BufferRelationship::ElementsParam(value)
75                    }
76                    ("NativeArrayInfoAttribute", "CountConst", Value::I32(value)) => {
77                        BufferRelationship::ElementsConst(value)
78                    }
79                    ("MemorySizeAttribute", "BytesParamIndex", Value::I16(value)) => {
80                        BufferRelationship::BytesParam(value)
81                    }
82                    ("NativeArrayInfoAttribute", "CountParamIndex" | "CountConst", _)
83                    | ("MemorySizeAttribute", "BytesParamIndex", _) => return None,
84                    _ => continue,
85                };
86
87                if result.replace(relationship).is_some() {
88                    return None;
89                }
90            }
91        }
92
93        result
94    }
95
96    pub fn sequence(&self) -> u16 {
97        self.usize(1).try_into().unwrap()
98    }
99
100    pub fn name(&self) -> &str {
101        self.str(2)
102    }
103}