1#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7#[non_exhaustive]
8pub enum TypeKind {
9 End,
11 Void,
13 Boolean,
15 Char,
17 I1,
19 U1,
21 I2,
23 U2,
25 I4,
27 U4,
29 I8,
31 U8,
33 R4,
35 R8,
37 String,
39 Ptr,
41 ByRef,
43 ValueType,
45 Class,
47 Var,
49 Array,
51 GenericInst,
53 TypedByRef,
55 I,
57 U,
59 FnPtr,
61 Object,
63 SzArray,
65 MVar,
67 Other(u32),
69}
70
71#[allow(clippy::too_many_lines)]
72impl From<u32> for TypeKind {
73 fn from(v: u32) -> Self {
74 match v {
75 0x00 => Self::End,
76 0x01 => Self::Void,
77 0x02 => Self::Boolean,
78 0x03 => Self::Char,
79 0x04 => Self::I1,
80 0x05 => Self::U1,
81 0x06 => Self::I2,
82 0x07 => Self::U2,
83 0x08 => Self::I4,
84 0x09 => Self::U4,
85 0x0a => Self::I8,
86 0x0b => Self::U8,
87 0x0c => Self::R4,
88 0x0d => Self::R8,
89 0x0e => Self::String,
90 0x0f => Self::Ptr,
91 0x10 => Self::ByRef,
92 0x11 => Self::ValueType,
93 0x12 => Self::Class,
94 0x13 => Self::Var,
95 0x14 => Self::Array,
96 0x15 => Self::GenericInst,
97 0x16 => Self::TypedByRef,
98 0x18 => Self::I,
99 0x19 => Self::U,
100 0x1b => Self::FnPtr,
101 0x1c => Self::Object,
102 0x1d => Self::SzArray,
103 0x1e => Self::MVar,
104 other => Self::Other(other),
105 }
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use std::collections::HashSet;
112
113 use super::TypeKind;
114
115 fn check(cases: &[(u32, TypeKind)]) {
116 for &(raw, ref expected) in cases {
117 assert_eq!(TypeKind::from(raw), *expected, "discriminant 0x{raw:02x}");
118 }
119 }
120
121 #[test]
122 fn primitive_variants_map_correctly() {
123 check(&[
124 (0x00, TypeKind::End),
125 (0x01, TypeKind::Void),
126 (0x02, TypeKind::Boolean),
127 (0x03, TypeKind::Char),
128 (0x04, TypeKind::I1),
129 (0x05, TypeKind::U1),
130 (0x06, TypeKind::I2),
131 (0x07, TypeKind::U2),
132 (0x08, TypeKind::I4),
133 (0x09, TypeKind::U4),
134 (0x0a, TypeKind::I8),
135 (0x0b, TypeKind::U8),
136 (0x0c, TypeKind::R4),
137 (0x0d, TypeKind::R8),
138 ]);
139 }
140
141 #[test]
142 fn reference_and_generic_variants_map_correctly() {
143 check(&[
144 (0x0e, TypeKind::String),
145 (0x0f, TypeKind::Ptr),
146 (0x10, TypeKind::ByRef),
147 (0x11, TypeKind::ValueType),
148 (0x12, TypeKind::Class),
149 (0x13, TypeKind::Var),
150 (0x14, TypeKind::Array),
151 (0x15, TypeKind::GenericInst),
152 (0x16, TypeKind::TypedByRef),
153 (0x18, TypeKind::I),
154 (0x19, TypeKind::U),
155 (0x1b, TypeKind::FnPtr),
156 (0x1c, TypeKind::Object),
157 (0x1d, TypeKind::SzArray),
158 (0x1e, TypeKind::MVar),
159 ]);
160 }
161
162 #[test]
163 fn gap_discriminants_produce_other() {
164 assert_eq!(TypeKind::from(0x17), TypeKind::Other(0x17));
166 assert_eq!(TypeKind::from(0x1a), TypeKind::Other(0x1a));
167 }
168
169 #[test]
170 fn high_discriminant_produces_other() {
171 assert_eq!(TypeKind::from(0xFF), TypeKind::Other(0xFF));
172 assert_eq!(TypeKind::from(100), TypeKind::Other(100));
173 }
174
175 #[test]
176 fn other_variants_equality_uses_inner_value() {
177 assert_eq!(TypeKind::Other(7), TypeKind::Other(7));
178 assert_ne!(TypeKind::Other(7), TypeKind::Other(8));
179 }
180
181 #[test]
182 fn type_kind_is_hashable() {
183 let mut set = HashSet::new();
184 set.insert(TypeKind::I4);
185 set.insert(TypeKind::I4);
186 set.insert(TypeKind::U4);
187 assert_eq!(set.len(), 2);
188 }
189
190 #[test]
191 fn type_kind_is_copy() {
192 let a = TypeKind::Boolean;
193 let b = a;
194 assert_eq!(a, b);
196 }
197
198 #[test]
199 fn type_kind_debug_contains_variant_name() {
200 assert!(format!("{:?}", TypeKind::I4).contains("I4"));
201 assert!(format!("{:?}", TypeKind::Other(99)).contains("Other"));
202 }
203}