1use std::fmt;
2use std::hash::{Hash, Hasher};
3
4#[derive(Clone, Debug, PartialEq, Eq, Hash)]
5pub enum Type {
6 Void,
7 Boolean,
8 Char,
9 Byte,
10 Short,
11 Int,
12 Float,
13 Long,
14 Double,
15 Array(Box<Type>),
17 Object(String),
19 Method {
21 argument_types: Vec<Type>,
22 return_type: Box<Type>,
23 },
24}
25
26impl Type {
27 pub const VOID_TYPE: Type = Type::Void;
28 pub const BOOLEAN_TYPE: Type = Type::Boolean;
29 pub const CHAR_TYPE: Type = Type::Char;
30 pub const BYTE_TYPE: Type = Type::Byte;
31 pub const SHORT_TYPE: Type = Type::Short;
32 pub const INT_TYPE: Type = Type::Int;
33 pub const FLOAT_TYPE: Type = Type::Float;
34 pub const LONG_TYPE: Type = Type::Long;
35 pub const DOUBLE_TYPE: Type = Type::Double;
36
37 pub fn get_type(descriptor: &str) -> Self {
42 let bytes = descriptor.as_bytes();
43 let mut pos = 0;
44 Self::parse(bytes, &mut pos)
45 }
46
47 pub fn get_object_type(internal_name: &str) -> Self {
50 if internal_name.starts_with('[') {
51 Self::get_type(internal_name)
52 } else {
53 Type::Object(internal_name.to_string())
54 }
55 }
56
57 pub fn get_method_type(descriptor: &str) -> Self {
62 let ty = Self::get_type(descriptor);
63 match ty {
64 Type::Method { .. } => ty,
65 _ => panic!("Not a method descriptor: {}", descriptor),
66 }
67 }
68
69 pub fn get_method_type_from_parts(return_type: Type, argument_types: Vec<Type>) -> Self {
71 Type::Method {
72 argument_types,
73 return_type: Box::new(return_type),
74 }
75 }
76
77 pub fn get_sort(&self) -> u8 {
79 match self {
80 Type::Void => 0,
81 Type::Boolean => 1,
82 Type::Char => 2,
83 Type::Byte => 3,
84 Type::Short => 4,
85 Type::Int => 5,
86 Type::Float => 6,
87 Type::Long => 7,
88 Type::Double => 8,
89 Type::Array(_) => 9,
90 Type::Object(_) => 10,
91 Type::Method { .. } => 11,
92 }
93 }
94
95 pub fn get_descriptor(&self) -> String {
97 match self {
98 Type::Void => "V".to_string(),
99 Type::Boolean => "Z".to_string(),
100 Type::Char => "C".to_string(),
101 Type::Byte => "B".to_string(),
102 Type::Short => "S".to_string(),
103 Type::Int => "I".to_string(),
104 Type::Float => "F".to_string(),
105 Type::Long => "J".to_string(),
106 Type::Double => "D".to_string(),
107 Type::Array(elem) => format!("[{}", elem.get_descriptor()),
108 Type::Object(name) => format!("L{};", name),
109 Type::Method {
110 argument_types,
111 return_type,
112 } => {
113 let mut desc = String::from("(");
114 for arg in argument_types {
115 desc.push_str(&arg.get_descriptor());
116 }
117 desc.push(')');
118 desc.push_str(&return_type.get_descriptor());
119 desc
120 }
121 }
122 }
123
124 pub fn get_class_name(&self) -> String {
126 match self {
127 Type::Void => "void".to_string(),
128 Type::Boolean => "boolean".to_string(),
129 Type::Char => "char".to_string(),
130 Type::Byte => "byte".to_string(),
131 Type::Short => "short".to_string(),
132 Type::Int => "int".to_string(),
133 Type::Float => "float".to_string(),
134 Type::Long => "long".to_string(),
135 Type::Double => "double".to_string(),
136 Type::Array(elem) => format!("{}[]", elem.get_class_name()),
137 Type::Object(name) => name.replace('/', "."),
138 Type::Method { .. } => panic!("get_class_name() called on a method type"),
139 }
140 }
141
142 pub fn internal_name(&self) -> Option<String> {
147 match self {
148 Type::Object(name) => Some(name.clone()),
149 Type::Array(_) => Some(self.get_descriptor()), _ => None,
151 }
152 }
153
154 pub fn get_dimensions(&self) -> usize {
157 match self {
158 Type::Array(elem) => 1 + elem.get_dimensions(),
159 _ => 0,
160 }
161 }
162
163 pub fn get_element_type(&self) -> Option<&Type> {
166 match self {
167 Type::Array(elem) => Some(elem),
168 _ => None,
169 }
170 }
171
172 pub fn get_argument_types(&self) -> Option<&[Type]> {
174 match self {
175 Type::Method { argument_types, .. } => Some(argument_types),
176 _ => None,
177 }
178 }
179
180 pub fn get_return_type(&self) -> Option<&Type> {
182 match self {
183 Type::Method { return_type, .. } => Some(return_type),
184 _ => None,
185 }
186 }
187
188 pub fn get_size(&self) -> usize {
190 match self {
191 Type::Void => 0,
192 Type::Long | Type::Double => 2,
193 _ => 1,
194 }
195 }
196
197 pub fn get_argument_count(&self) -> usize {
200 match self {
201 Type::Method { argument_types, .. } => argument_types.len(),
202 _ => panic!("get_argument_count() called on a non-method type"),
203 }
204 }
205
206 fn parse(bytes: &[u8], pos: &mut usize) -> Self {
209 let c = bytes[*pos] as char;
210 match c {
211 'V' => {
212 *pos += 1;
213 Type::Void
214 }
215 'Z' => {
216 *pos += 1;
217 Type::Boolean
218 }
219 'C' => {
220 *pos += 1;
221 Type::Char
222 }
223 'B' => {
224 *pos += 1;
225 Type::Byte
226 }
227 'S' => {
228 *pos += 1;
229 Type::Short
230 }
231 'I' => {
232 *pos += 1;
233 Type::Int
234 }
235 'F' => {
236 *pos += 1;
237 Type::Float
238 }
239 'J' => {
240 *pos += 1;
241 Type::Long
242 }
243 'D' => {
244 *pos += 1;
245 Type::Double
246 }
247 'L' => {
248 *pos += 1; let start = *pos;
250 while bytes[*pos] != b';' {
251 *pos += 1;
252 }
253 let name = std::str::from_utf8(&bytes[start..*pos])
254 .expect("Invalid UTF-8 in internal name")
255 .to_string();
256 *pos += 1; Type::Object(name)
258 }
259 '[' => {
260 *pos += 1; let elem = Box::new(Self::parse(bytes, pos));
262 Type::Array(elem)
263 }
264 '(' => {
265 *pos += 1; let mut args = Vec::new();
267 while bytes[*pos] != b')' {
268 args.push(Self::parse(bytes, pos));
269 }
270 *pos += 1; let ret = Box::new(Self::parse(bytes, pos));
272 Type::Method {
273 argument_types: args,
274 return_type: ret,
275 }
276 }
277 _ => panic!("Invalid descriptor character: {}", c),
278 }
279 }
280}
281
282impl fmt::Display for Type {
283 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
284 write!(f, "{}", self.get_descriptor())
285 }
286}