windows_metadata/reader/
codes.rs1use super::*;
2
3pub trait Decode<'a> {
4 fn decode(index: &'a Index, file: usize, code: usize) -> Self;
5}
6
7macro_rules! code {
8 ($name:ident($size:literal) $(($table:ident, $code:literal))+) => {
9 #[derive(Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
10 pub enum $name<'a> {
11 $($table($table<'a>),)*
12 }
13 impl<'a> Decode<'a> for $name<'a> {
14 fn decode(index: &'a Index, file: usize, code: usize) -> Self {
15 let (kind, row) = (code & ((1 << $size) - 1), (code >> $size) - 1);
16 match kind {
17 $($code => Self::$table($table(Row::new(index, file, row))),)*
18 rest => panic!("{rest:?}"),
19 }
20 }
21 }
22 impl $name<'_> {
23 pub fn encode(&self) -> usize {
24 match self {
25 $(Self::$table(row) => (row.pos() + 1) << $size | $code,)*
26 }
27 }
28 }
29 $(
30 impl<'a> From<$table<'a>> for $name<'a> {
31 fn from(from: $table<'a>) -> Self {
32 Self::$table(from)
33 }
34 }
35 )*
36 };
37}
38
39code! { AttributeType(3)
40 (MethodDef, 2)
41 (MemberRef, 3)
42}
43
44impl<'a> AttributeType<'a> {
45 pub fn parent(&self) -> MemberRefParent<'a> {
46 match self {
47 Self::MethodDef(row) => row.parent(),
48 Self::MemberRef(row) => row.parent(),
49 }
50 }
51
52 pub fn signature(&self, generics: &[Type]) -> Signature {
53 match self {
54 Self::MethodDef(row) => row.signature(generics),
55 Self::MemberRef(row) => row.signature(generics),
56 }
57 }
58}
59
60code! { HasAttribute(5)
61 (MethodDef, 0)
62 (Field, 1)
63 (TypeRef, 2)
64 (TypeDef, 3)
65 (MethodParam, 4)
66 (InterfaceImpl, 5)
67 (MemberRef, 6)
68 (TypeSpec, 13)
69 (GenericParam, 19)
70}
71
72code! { HasConstant(2)
73 (Field, 0)
74}
75
76code! { MemberForwarded(1)
77 (MethodDef, 1)
78}
79
80code! { MemberRefParent(3)
81 (TypeDef, 0)
82 (TypeRef, 1)
83}
84
85impl<'a> MemberRefParent<'a> {
86 pub fn namespace(&self) -> &'a str {
87 match self {
88 Self::TypeDef(row) => row.namespace(),
89 Self::TypeRef(row) => row.namespace(),
90 }
91 }
92
93 pub fn name(&self) -> &'a str {
94 match self {
95 Self::TypeDef(row) => row.name(),
96 Self::TypeRef(row) => row.name(),
97 }
98 }
99}
100
101code! { TypeDefOrRef(2)
102 (TypeDef, 0)
103 (TypeRef, 1)
104 (TypeSpec, 2)
105}
106
107code! { TypeOrMethodDef(1)
108 (TypeDef, 0)
109 (MethodDef, 1)
110}
111
112impl<'a> TypeDefOrRef<'a> {
113 pub fn namespace(&self) -> &'a str {
114 match self {
115 Self::TypeDef(row) => row.namespace(),
116 Self::TypeRef(row) => row.namespace(),
117 rest => panic!("{rest:?}"),
118 }
119 }
120
121 pub fn name(&self) -> &'a str {
122 match self {
123 Self::TypeDef(row) => row.name(),
124 Self::TypeRef(row) => row.name(),
125 rest => panic!("{rest:?}"),
126 }
127 }
128
129 pub fn ty(&self, generics: &[Type]) -> Type {
130 if let Self::TypeSpec(def) = self {
131 return def.ty(generics);
132 }
133
134 if let Self::TypeDef(def) = self {
135 let tn = TypeName::named(def.namespace(), def.name());
136 return match def.category() {
137 TypeCategory::Struct | TypeCategory::Enum => Type::ValueName(tn),
138 _ => Type::ClassName(tn),
139 };
140 }
141
142 Type::ClassName(TypeName::named(self.namespace(), self.name()))
143 }
144}
145
146impl PartialEq<(&str, &str)> for &TypeDefOrRef<'_> {
147 fn eq(&self, other: &(&str, &str)) -> bool {
148 *self == other
149 }
150}
151
152impl PartialEq<(&str, &str)> for TypeDefOrRef<'_> {
153 fn eq(&self, other: &(&str, &str)) -> bool {
154 self.namespace() == other.0 && self.name() == other.1
155 }
156}
157
158code! { ResolutionScope(2)
159 (Module, 0)
160 (ModuleRef, 1)
161 (AssemblyRef, 2)
162 (TypeRef, 3)
163}