Skip to main content

windows_metadata/reader/
codes.rs

1use 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}