1#![allow(non_camel_case_types)]
2
3use std::fmt;
22use log::warn;
23
24#[derive(Debug)]
26pub enum AccessFlagType {
27 Class,
29 Field,
31 Method
33}
34
35impl fmt::Display for AccessFlagType {
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 match *self {
39 AccessFlagType::Class => { write!(f, "class") },
40 AccessFlagType::Field => { write!(f, "field") },
41 AccessFlagType::Method => { write!(f, "method") }
42 }
43 }
44}
45
46#[derive(Debug, PartialEq)]
51pub enum AccessFlag {
52 ACC_PUBLIC,
54 ACC_PRIVATE,
56 ACC_PROTECTED,
58 ACC_STATIC,
63 ACC_FINAL,
68 ACC_SYNCHRONIZED,
72 ACC_VOLATILE,
75 ACC_BRIDGE,
78 ACC_TRANSIENT,
81 ACC_VARARGS,
84 ACC_NATIVE,
87 ACC_INTERFACE,
89 ACC_ABSTRACT,
93 ACC_STRICT,
96 ACC_SYNTHETIC,
98 ACC_ANNOTATION,
100 ACC_ENUM,
104 ACC_CONSTRUCTOR,
106 ACC_DECLARED_SYNCHRONIZED,
109}
110
111impl AccessFlag {
112 pub fn parse(raw: u32, for_type: AccessFlagType) -> Vec<Self> {
117 let mut flags = Vec::new();
118
119 if raw & 0x01 != 0 { flags.push(AccessFlag::ACC_PUBLIC); }
120 if raw & 0x02 != 0 { flags.push(AccessFlag::ACC_PRIVATE); }
121 if raw & 0x04 != 0 { flags.push(AccessFlag::ACC_PROTECTED); }
122 if raw & 0x08 != 0 { flags.push(AccessFlag::ACC_STATIC); }
123 if raw & 0x10 != 0 { flags.push(AccessFlag::ACC_FINAL); }
124 if raw & 0x20 != 0 {
125 match for_type {
126 AccessFlagType::Method => {
127 flags.push(AccessFlag::ACC_SYNCHRONIZED);
128 },
129 _ => {
130 warn!("Ignoring invalid flag for {for_type}: 0x20");
131 }
132 }
133 }
134 if raw & 0x40 != 0 {
135 match for_type {
136 AccessFlagType::Class => {
137 warn!("Ignoring invalid flag for {for_type}: 0x40");
138 },
139 AccessFlagType::Field => {
140 flags.push(AccessFlag::ACC_VOLATILE);
141 },
142 AccessFlagType::Method => {
143 flags.push(AccessFlag::ACC_BRIDGE);
144 }
145 }
146 }
147 if raw & 0x80 != 0 {
148 match for_type {
149 AccessFlagType::Class => {
150 warn!("Ignoring invalid flag for {for_type}: 0x80");
151 },
152 AccessFlagType::Field => {
153 flags.push(AccessFlag::ACC_TRANSIENT);
154 },
155 AccessFlagType::Method => {
156 flags.push(AccessFlag::ACC_VARARGS);
157 }
158 }
159 }
160 if raw & 0x100 != 0 {
161 match for_type {
162 AccessFlagType::Method => {
163 flags.push(AccessFlag::ACC_NATIVE);
164 },
165 _ => {
166 warn!("Ignoring invalid flag for {for_type}: 0x100");
167 }
168 }
169 }
170 if raw & 0x200 != 0 {
171 match for_type {
172 AccessFlagType::Class => {
173 flags.push(AccessFlag::ACC_INTERFACE);
174 },
175 _ => {
176 warn!("Ignoring invalid flag for {for_type}: 0x200");
177 }
178 }
179 }
180 if raw & 0x400 != 0 {
181 match for_type {
182 AccessFlagType::Field => {
183 warn!("Ignoring invalid flag for {for_type}: 0x400");
184 },
185 _ => {
186 flags.push(AccessFlag::ACC_ABSTRACT);
187 }
188 }
189 }
190 if raw & 0x800 != 0 {
191 match for_type {
192 AccessFlagType::Method => {
193 flags.push(AccessFlag::ACC_STRICT);
194 },
195 _ => {
196 warn!("Ignoring invalid flag for {for_type}: 0x800");
197 }
198 }
199 }
200 if raw & 0x1000 != 0 { flags.push(AccessFlag::ACC_SYNTHETIC); }
201 if raw & 0x2000 != 0 {
202 match for_type {
203 AccessFlagType::Class => {
204 flags.push(AccessFlag::ACC_ANNOTATION);
205 },
206 _ => {
207 warn!("Ignoring invalid flag for {for_type}: 0x2000");
208 }
209 }
210 }
211 if raw & 0x4000 != 0 {
212 match for_type {
213 AccessFlagType::Method => {
214 warn!("Ignoring invalid flag for {for_type}: 0x4000");
215 },
216 _ => {
217 flags.push(AccessFlag::ACC_ENUM);
218 }
219 }
220 }
221 if raw & 0x8000 != 0 { warn!("Ignoring invalid (unused) flag: 0x8000"); }
222 if raw & 0x10000 != 0 {
223 match for_type {
224 AccessFlagType::Method => {
225 flags.push(AccessFlag::ACC_CONSTRUCTOR);
226 },
227 _ => {
228 warn!("Ignoring invalid flag for {for_type}: 0x10000");
229 }
230 }
231 }
232 if raw & 0x20000 != 0 {
233 match for_type {
234 AccessFlagType::Method => {
235 flags.push(AccessFlag::ACC_DECLARED_SYNCHRONIZED);
236 },
237 _ => {
238 warn!("Ignoring invalid flag for {for_type}: 0x20000");
239 }
240 }
241 }
242
243 flags
244 }
245
246 pub fn vec_to_string(flags: &[AccessFlag]) -> String {
248 let mut output = String::new();
249 let flags_len = flags.len();
250
251 for (idx, flag) in flags.iter().enumerate() {
252 output.push_str(&flag.to_string());
253 if idx < flags_len - 1{
254 output.push('|');
255 }
256 }
257
258 output
259 }
260}
261
262impl fmt::Display for AccessFlag {
264 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
265 match *self {
266 AccessFlag::ACC_PUBLIC => write!(f, "public" ),
267 AccessFlag::ACC_PRIVATE => write!(f, "private" ),
268 AccessFlag::ACC_PROTECTED => write!(f, "protected" ),
269 AccessFlag::ACC_STATIC => write!(f, "static" ),
270 AccessFlag::ACC_FINAL => write!(f, "final" ),
271 AccessFlag::ACC_SYNCHRONIZED => write!(f, "synchronized" ),
272 AccessFlag::ACC_VOLATILE => write!(f, "volatile" ),
273 AccessFlag::ACC_BRIDGE => write!(f, "bridge" ),
274 AccessFlag::ACC_TRANSIENT => write!(f, "transient" ),
275 AccessFlag::ACC_VARARGS => write!(f, "varargs" ),
276 AccessFlag::ACC_NATIVE => write!(f, "native" ),
277 AccessFlag::ACC_INTERFACE => write!(f, "interface" ),
278 AccessFlag::ACC_ABSTRACT => write!(f, "abstract" ),
279 AccessFlag::ACC_STRICT => write!(f, "strict" ),
280 AccessFlag::ACC_SYNTHETIC => write!(f, "synthetic" ),
281 AccessFlag::ACC_ANNOTATION => write!(f, "annotation" ),
282 AccessFlag::ACC_ENUM => write!(f, "enum" ),
283 AccessFlag::ACC_CONSTRUCTOR => write!(f, "constructor" ),
284 AccessFlag::ACC_DECLARED_SYNCHRONIZED => write!(f, "synchronized" ),
285 }
286 }
287}
288
289#[cfg(test)]
290mod tests {
291 use super::*;
292
293 #[test]
294 fn test_access_flag_type_display() {
295 let class_flag = AccessFlagType::Class;
296 let field_flag = AccessFlagType::Field;
297 let method_flag = AccessFlagType::Method;
298
299 assert_eq!(class_flag.to_string(), "class");
300 assert_eq!(field_flag.to_string(), "field");
301 assert_eq!(method_flag.to_string(), "method");
302 }
303
304 #[test]
305 fn test_access_flag_class_parse() {
306 let flags = AccessFlag::parse(0x3ffff, AccessFlagType::Class);
309 assert_eq!(flags, vec![AccessFlag::ACC_PUBLIC,
310 AccessFlag::ACC_PRIVATE,
311 AccessFlag::ACC_PROTECTED,
312 AccessFlag::ACC_STATIC,
313 AccessFlag::ACC_FINAL,
314 AccessFlag::ACC_INTERFACE,
315 AccessFlag::ACC_ABSTRACT,
316 AccessFlag::ACC_SYNTHETIC,
317 AccessFlag::ACC_ANNOTATION,
318 AccessFlag::ACC_ENUM]);
319 }
320
321 #[test]
322 fn test_access_flag_field_parse() {
323 let flags = AccessFlag::parse(0x3ffff, AccessFlagType::Field);
326 assert_eq!(flags, vec![AccessFlag::ACC_PUBLIC,
327 AccessFlag::ACC_PRIVATE,
328 AccessFlag::ACC_PROTECTED,
329 AccessFlag::ACC_STATIC,
330 AccessFlag::ACC_FINAL,
331 AccessFlag::ACC_VOLATILE,
332 AccessFlag::ACC_TRANSIENT,
333 AccessFlag::ACC_SYNTHETIC,
334 AccessFlag::ACC_ENUM]);
335 }
336
337 #[test]
338 fn test_access_flag_method_parse() {
339 let flags = AccessFlag::parse(0x3ffff, AccessFlagType::Method);
342 assert_eq!(flags, vec![AccessFlag::ACC_PUBLIC,
343 AccessFlag::ACC_PRIVATE,
344 AccessFlag::ACC_PROTECTED,
345 AccessFlag::ACC_STATIC,
346 AccessFlag::ACC_FINAL,
347 AccessFlag::ACC_SYNCHRONIZED,
348 AccessFlag::ACC_BRIDGE,
349 AccessFlag::ACC_VARARGS,
350 AccessFlag::ACC_NATIVE,
351 AccessFlag::ACC_ABSTRACT,
352 AccessFlag::ACC_STRICT,
353 AccessFlag::ACC_SYNTHETIC,
354 AccessFlag::ACC_CONSTRUCTOR,
355 AccessFlag::ACC_DECLARED_SYNCHRONIZED]);
356 }
357}