windows_metadata/reader/tables/
method_def.rs1use super::*;
2
3#[derive(Clone, Debug)]
5pub struct MethodParamMap<'a> {
6 return_param: Option<MethodParam<'a>>,
7 params: Vec<Option<MethodParam<'a>>>,
8}
9
10impl<'a> MethodParamMap<'a> {
11 pub fn return_param(&self) -> Option<MethodParam<'a>> {
13 self.return_param
14 }
15
16 pub fn params(&self) -> &[Option<MethodParam<'a>>] {
18 &self.params
19 }
20}
21
22#[derive(Copy, Clone, Debug, PartialEq, Eq)]
24pub enum MethodParamSequenceError {
25 DuplicateSequence {
26 sequence: u16,
27 },
28 SequenceOutOfRange {
29 sequence: u16,
30 parameter_count: usize,
31 },
32}
33
34impl std::fmt::Display for MethodParamSequenceError {
35 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
36 match self {
37 Self::DuplicateSequence { sequence } => {
38 write!(f, "duplicate Param.Sequence {sequence}")
39 }
40 Self::SequenceOutOfRange {
41 sequence,
42 parameter_count,
43 } => write!(
44 f,
45 "Param.Sequence {sequence} is out of range for {parameter_count} signature \
46 parameters"
47 ),
48 }
49 }
50}
51
52impl std::error::Error for MethodParamSequenceError {}
53
54impl std::fmt::Debug for MethodDef<'_> {
55 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
56 f.debug_tuple("MethodDef").field(&self.name()).finish()
57 }
58}
59
60impl<'a> MethodDef<'a> {
61 pub fn impl_flags(&self) -> MethodImplAttributes {
62 MethodImplAttributes(self.usize(1).try_into().unwrap())
63 }
64
65 pub fn flags(&self) -> MethodAttributes {
66 MethodAttributes(self.usize(2).try_into().unwrap())
67 }
68
69 pub fn name(&self) -> &'a str {
70 self.str(3)
71 }
72
73 pub fn signature(&self, generics: &[Type]) -> Signature {
74 self.blob(4).read_method_signature(generics)
75 }
76
77 pub fn params(&self) -> RowIterator<'a, MethodParam<'a>> {
81 self.list(5)
82 }
83
84 pub fn params_by_sequence(
91 &self,
92 parameter_count: usize,
93 ) -> Result<MethodParamMap<'a>, MethodParamSequenceError> {
94 let mut return_param = None;
95 let mut params = vec![None; parameter_count];
96
97 for param in self.params() {
98 let sequence = param.sequence();
99 if sequence == 0 {
100 if return_param.replace(param).is_some() {
101 return Err(MethodParamSequenceError::DuplicateSequence { sequence });
102 }
103 continue;
104 }
105
106 let position = sequence as usize - 1;
107 let Some(slot) = params.get_mut(position) else {
108 return Err(MethodParamSequenceError::SequenceOutOfRange {
109 sequence,
110 parameter_count,
111 });
112 };
113 if slot.replace(param).is_some() {
114 return Err(MethodParamSequenceError::DuplicateSequence { sequence });
115 }
116 }
117
118 Ok(MethodParamMap {
119 return_param,
120 params,
121 })
122 }
123
124 pub fn parent(&self) -> MemberRefParent<'a> {
125 MemberRefParent::TypeDef(self.parent_row(5))
126 }
127
128 pub fn impl_map(&self) -> Option<ImplMap<'a>> {
129 self.equal_range(1, MemberForwarded::MethodDef(*self).encode())
130 .next()
131 }
132
133 pub fn calling_convention(&self) -> &'static str {
134 self.impl_map().map_or("", |map| {
135 let flags = map.flags();
136
137 if flags.contains(PInvokeAttributes::CallConvPlatformapi) {
138 "system"
139 } else if flags.contains(PInvokeAttributes::CallConvCdecl) {
140 "C"
141 } else {
142 ""
143 }
144 })
145 }
146}