1use crate::classfile::{
2 attributes::{self, Tag as AttrTag, TargetInfo, TypeAnnotation},
3 constant_pool, AttributeType, ClassFile, ConstantPool, FieldInfo, MethodInfo, Version,
4};
5use std::sync::Arc;
6
7use nom::{
8 call, count, do_parse, named, named_args,
9 number::streaming::{be_u16, be_u32, be_u8},
10 peek, switch, tag, take, value,
11};
12
13named!(
14 version<Version>,
15 do_parse!(minor: be_u16 >> major: be_u16 >> (Version { minor, major }))
16);
17
18named!(
19 constant_tag<constant_pool::Tag>,
20 do_parse!(tag: be_u8 >> (constant_pool::Tag::from(tag)))
21);
22
23macro_rules! gen_take_exact {
27 ($count: expr, $name: ident) => {
28 fn $name(input: &[u8]) -> nom::IResult<&[u8], [u8; $count]> {
29 let mut output = [0; $count];
30 assert!(input.len() >= $count);
32 for i in 0..$count {
33 output[i] = input[i];
34 }
35 Ok((&input[$count..], output))
36 }
37 };
38}
39
40gen_take_exact!(4, take_exact_4);
41gen_take_exact!(8, take_exact_8);
42
43named!(
44 cp_entry<constant_pool::Type>,
45 do_parse!(
46 ct: constant_tag
47 >> entry:
48 switch!(value!(ct),
49 constant_pool::Tag::Class => do_parse!(
50 name_index: be_u16 >>
51 (constant_pool::Type::Class { name_index })
52 ) |
53 constant_pool::Tag::FieldRef => do_parse!(
54 class_index: be_u16 >>
55 name_and_type_index: be_u16 >>
56 (constant_pool::Type::FieldRef { class_index, name_and_type_index })
57 ) |
58 constant_pool::Tag::MethodRef => do_parse!(
59 class_index: be_u16 >>
60 name_and_type_index: be_u16 >>
61 (constant_pool::Type::MethodRef { class_index, name_and_type_index })
62 ) |
63 constant_pool::Tag::InterfaceMethodRef => do_parse!(
64 class_index: be_u16 >>
65 name_and_type_index: be_u16 >>
66 (constant_pool::Type::InterfaceMethodRef { class_index, name_and_type_index })
67 ) |
68 constant_pool::Tag::String => do_parse!(
69 string_index: be_u16 >>
70 (constant_pool::Type::String { string_index })
71 ) |
72 constant_pool::Tag::Integer => do_parse!(
73 v: take_exact_4 >>
74 (constant_pool::Type::Integer { v })
75 ) |
76 constant_pool::Tag::Float => do_parse!(
77 v: take_exact_4 >>
78 (constant_pool::Type::Float { v })
79 ) |
80 constant_pool::Tag::Long => do_parse!(
81 v: take_exact_8 >>
82 (constant_pool::Type::Long { v })
83 ) |
84 constant_pool::Tag::Double => do_parse!(
85 v: take_exact_8 >>
86 (constant_pool::Type::Double { v })
87 ) |
88 constant_pool::Tag::NameAndType => do_parse!(
89 name_index: be_u16 >>
90 desc_index: be_u16 >>
91 (constant_pool::Type::NameAndType { name_index, desc_index })
92 ) |
93 constant_pool::Tag::Utf8 => do_parse!(
94 length: be_u16 >>
95 bytes: take!(length) >>
96 (constant_pool::Type::Utf8 { bytes: Arc::new(Vec::from(bytes)) })
97 ) |
98 constant_pool::Tag::MethodHandle => do_parse!(
99 ref_kind: be_u8 >>
100 ref_index: be_u16 >>
101 (constant_pool::Type::MethodHandle { ref_kind, ref_index })
102 ) |
103 constant_pool::Tag::MethodType => do_parse!(
104 desc_index: be_u16 >>
105 (constant_pool::Type::MethodType { desc_index })
106 ) |
107 constant_pool::Tag::InvokeDynamic => do_parse!(
108 bootstrap_method_attr_index: be_u16 >>
109 name_and_type_index: be_u16 >>
110 (constant_pool::Type::InvokeDynamic { bootstrap_method_attr_index, name_and_type_index })
111 )
112 )
113 >> (entry)
114 )
115);
116
117fn constant_pool(input: &[u8]) -> nom::IResult<&[u8], ConstantPool> {
118 let (mut input, count) = be_u16(input)?;
119
120 let mut output = Vec::with_capacity(count as usize);
121 output.push(constant_pool::Type::Nop);
122
123 let mut i = 1;
124 while i < count {
125 let (new_input, constant_type) = cp_entry(input)?;
126 input = new_input;
127
128 i += 1;
129 output.push(constant_type.clone());
130
131 match constant_type {
133 constant_pool::Type::Long { .. } | constant_pool::Type::Double { .. } => {
134 i += 1;
135 output.push(constant_pool::Type::Nop);
136 }
137 _ => (),
138 }
139 }
140
141 Ok((input, Arc::new(output)))
142}
143
144use attributes::VerificationTypeInfo;
145named!(
146 verification_type_info<VerificationTypeInfo>,
147 do_parse!(
148 id: be_u8
149 >> inner:
150 switch!(value!(id),
151 0 => value!(VerificationTypeInfo::Top) |
152 1 => value!(VerificationTypeInfo::Integer) |
153 2 => value!(VerificationTypeInfo::Float) |
154 3 => value!(VerificationTypeInfo::Long) |
155 4 => value!(VerificationTypeInfo::Double) |
156 5 => value!(VerificationTypeInfo::Null) |
157 6 => value!(VerificationTypeInfo::UninitializedThis) |
158 7 => do_parse!(
159 cpool_index: be_u16 >>
160 (VerificationTypeInfo::Object {cpool_index})
161 ) |
162 8 => do_parse!(
163 offset: be_u16 >>
164 (VerificationTypeInfo::Uninitialized {offset})
165 )
166 )
167 >> (inner)
168 )
169);
170
171named!(
172 stack_map_frame<attributes::StackMapFrame>,
173 do_parse!(
174 frame_type: be_u8
175 >> inner:
176 switch!(value!(frame_type),
177 0..=63 => value!(attributes::StackMapFrame::Same {tag: frame_type, offset_delta: frame_type as u16}) |
178 64..=127 => do_parse!(
179 offset_delta: value!((frame_type-64) as u16) >>
180 type_info: verification_type_info >>
181 (attributes::StackMapFrame::SameLocals1StackItem {
182 tag: frame_type,
183 offset_delta,
184 stack: [type_info],
185 })
186 ) |
187 128..=246 => value!(attributes::StackMapFrame::Reserved(frame_type)) |
188 247 => do_parse!(
189 offset_delta: be_u16 >>
190 type_info: verification_type_info >>
191 (attributes::StackMapFrame::SameLocals1StackItem {
192 tag: frame_type,
193 offset_delta,
194 stack: [type_info],
195 })
196 ) |
197 248..=250 => do_parse!(
198 offset_delta: be_u16 >>
199 (attributes::StackMapFrame::Chop {
200 tag: frame_type,
201 offset_delta,
202 })
203 ) |
204 251 => do_parse!(
205 offset_delta: be_u16 >>
206 (attributes::StackMapFrame::SameExtended {
207 tag: frame_type,
208 offset_delta
209 })
210 ) |
211 252..=254 => do_parse!(
212 offset_delta: be_u16 >>
213 locals_count: value!(frame_type - 251) >>
214 locals: count!(verification_type_info, locals_count as usize) >>
215 (attributes::StackMapFrame::Append {
216 tag: frame_type,
217 offset_delta,
218 locals,
219 })
220 ) |
221 255 => do_parse!(
222 offset_delta: be_u16 >>
223 locals_count: be_u16 >>
224 locals: count!(verification_type_info, locals_count as usize) >>
225 stack_count: be_u16 >>
226 stack: count!(verification_type_info, stack_count as usize) >>
227 (attributes::StackMapFrame::Full {
228 tag: frame_type,
229 offset_delta,
230 locals,
231 stack,
232 })
233 )
234 )
235 >> (inner)
236 )
237);
238
239named!(
240 inner_class<attributes::InnerClass>,
241 do_parse!(
242 inner_class_info_index: be_u16
243 >> outer_class_info_index: be_u16
244 >> inner_name_index: be_u16
245 >> inner_class_access_flags: be_u16
246 >> (attributes::InnerClass {
247 inner_class_info_index,
248 outer_class_info_index,
249 inner_name_index,
250 inner_class_access_flags,
251 })
252 )
253);
254
255named!(
256 enclosing_method<attributes::EnclosingMethod>,
257 do_parse!(
258 class_index: be_u16
259 >> method_index: be_u16
260 >> (attributes::EnclosingMethod {
261 class_index,
262 method_index,
263 })
264 )
265);
266
267named!(
268 line_number<attributes::LineNumber>,
269 do_parse!(start_pc: be_u16 >> number: be_u16 >> (attributes::LineNumber { start_pc, number }))
270);
271
272named!(
273 local_variable<attributes::LocalVariable>,
274 do_parse!(
275 start_pc: be_u16
276 >> length: be_u16
277 >> name_index: be_u16
278 >> signature_index: be_u16
279 >> index: be_u16
280 >> (attributes::LocalVariable {
281 start_pc,
282 length,
283 name_index,
284 signature_index,
285 index,
286 })
287 )
288);
289
290named!(
291 element_value_tag<attributes::ElementValueTag>,
292 do_parse!(tag: be_u8 >> (attributes::ElementValueTag::from(tag)))
293);
294
295use attributes::{ElementValueTag, ElementValueType};
296
297named_args!(element_value_type(cp: ConstantPool)<attributes::ElementValueType>, do_parse!(
299 tag: element_value_tag >>
300 inner: switch!(value!(tag),
301 ElementValueTag::Byte => do_parse!(
302 val_index: be_u16 >>
303 (ElementValueType::Byte {val_index})
304 ) |
305 ElementValueTag::Char => do_parse!(
306 val_index: be_u16 >>
307 (ElementValueType::Char {val_index})
308 ) |
309 ElementValueTag::Double => do_parse!(
310 val_index: be_u16 >>
311 (ElementValueType::Double {val_index})
312 ) |
313 ElementValueTag::Float => do_parse!(
314 val_index: be_u16 >>
315 (ElementValueType::Float {val_index})
316 ) |
317 ElementValueTag::Byte => do_parse!(
318 val_index: be_u16 >>
319 (ElementValueType::Byte {val_index})
320 ) |
321 ElementValueTag::Int => do_parse!(
322 val_index: be_u16 >>
323 (ElementValueType::Int {val_index})
324 ) |
325 ElementValueTag::Long => do_parse!(
326 val_index: be_u16 >>
327 (ElementValueType::Long {val_index})
328 ) |
329 ElementValueTag::Short => do_parse!(
330 val_index: be_u16 >>
331 (ElementValueType::Short {val_index})
332 ) |
333 ElementValueTag::Boolean => do_parse!(
334 val_index: be_u16 >>
335 (ElementValueType::Boolean {val_index})
336 ) |
337 ElementValueTag::String => do_parse!(
338 val_index: be_u16 >>
339 (ElementValueType::String {val_index})
340 ) |
341 ElementValueTag::Enum => do_parse!(
342 type_index: be_u16 >>
343 val_index: be_u16 >>
344 (ElementValueType::Enum {type_index, val_index})
345 ) |
346 ElementValueTag::Class => do_parse!(
347 index: be_u16 >>
348 (ElementValueType::Class {index})
349 ) |
350 ElementValueTag::Annotation => do_parse!(
351 value: call!(annotation_entry, cp) >>
352 (ElementValueType::Annotation(attributes::AnnotationElementValue {value}))
353 ) |
354 ElementValueTag::Array => do_parse!(
355 array_size: be_u16 >>
356 values: count!(call!(element_value_type, cp.clone()), array_size as usize) >>
357 (ElementValueType::Array {
358 values,
359 })
360 ) |
361 ElementValueTag::Unknown => value!(ElementValueType::Unknown)
362 ) >>
363 (inner)
364));
365
366named_args!(element_value_pair(cp: ConstantPool)<attributes::ElementValuePair>, do_parse!(
367 name_index: be_u16 >>
368 value: call!(element_value_type, cp) >>
369 (attributes::ElementValuePair {name_index, value})
370));
371
372named_args!(annotation_entry(cp: ConstantPool)<attributes::AnnotationEntry>, do_parse!(
373 type_index: be_u16 >>
374 pair_count: be_u16 >>
375 pairs: count!(call!(element_value_pair, cp.clone()), pair_count as usize) >>
376 type_name: value!(constant_pool::get_utf8(&cp, type_index as usize).expect("Missing type name")) >>
377 (attributes::AnnotationEntry {type_name, pairs})
378));
379
380named!(
381 local_var_target_table<attributes::LocalVarTargetTable>,
382 do_parse!(
383 start_pc: be_u16
384 >> length: be_u16
385 >> index: be_u16
386 >> (attributes::LocalVarTargetTable {
387 start_pc,
388 length,
389 index
390 })
391 )
392);
393
394named!(
395 target_info<TargetInfo>,
396 do_parse!(
397 target_type: be_u8
398 >> inner:
399 switch!(value!(target_type),
400 0x00 | 0x01 => do_parse!(
401 type_parameter_index: be_u8 >>
402 (TargetInfo::TypeParameter { type_parameter_index })
403 ) |
404 0x10 => do_parse!(
405 supertype_index: be_u16 >>
406 (TargetInfo::SuperType { supertype_index })
407 ) |
408 0x11 | 0x12 => do_parse!(
409 type_parameter_index: be_u8 >>
410 bound_index: be_u8 >>
411 (TargetInfo::TypeParameterBound {type_parameter_index, bound_index})
412 ) |
413 0x13 | 0x14 | 0x15 => value!(TargetInfo::Empty) |
414 0x16 => do_parse!(
415 formal_parameter_index: be_u8 >>
416 (TargetInfo::FormalParameter {formal_parameter_index})
417 ) |
418 0x17 => do_parse!(
419 throws_type_index: be_u16 >>
420 (TargetInfo::Throws {throws_type_index})
421 ) |
422 0x40 | 0x41 => do_parse!(
423 item_count: be_u16 >>
424 items: count!(local_var_target_table, item_count as usize) >>
425 (TargetInfo::LocalVar {table: items})
426 ) |
427 0x42 => do_parse!(
428 exception_table_index: be_u16 >>
429 (TargetInfo::Catch {exception_table_index})
430 ) |
431 0x43 | 0x44 | 0x45 | 0x46 => do_parse!(
432 offset: be_u16 >>
433 (TargetInfo::Offset {offset})
434 ) |
435 0x47 | 0x48 | 0x49 | 0x4A | 0x4B => do_parse!(
436 offset: be_u16 >>
437 type_argument_index: be_u8 >>
438 (TargetInfo::TypeArgument {offset, type_argument_index})
439 )
440 )
441 >> (inner)
442 )
443);
444
445named!(
446 type_path<attributes::TypePath>,
447 do_parse!(
448 type_path_kind: be_u8
449 >> type_argument_index: be_u8
450 >> (attributes::TypePath {
451 type_path_kind,
452 type_argument_index,
453 })
454 )
455);
456
457named_args!(type_annotation(cp: ConstantPool)<TypeAnnotation>, do_parse!(
458 target_info: target_info >>
459 target_path_part_count: be_u8 >>
460 target_path: count!(type_path, target_path_part_count as usize) >>
461 type_index: be_u16 >>
462 pair_count: be_u16 >>
463 pairs: count!(call!(element_value_pair, cp.clone()), pair_count as usize) >>
464 (attributes::TypeAnnotation {
465 target_info,
466 target_path,
467 type_index,
468 pairs,
469 })
470));
471
472named!(
473 bootstrap_method<attributes::BootstrapMethod>,
474 do_parse!(
475 method_ref: be_u16
476 >> arg_count: be_u16
477 >> args: count!(be_u16, arg_count as usize)
478 >> (attributes::BootstrapMethod { method_ref, args })
479 )
480);
481
482named!(
483 method_parameter<attributes::MethodParameter>,
484 do_parse!(
485 name_index: be_u16
486 >> acc_flags: be_u16
487 >> (attributes::MethodParameter {
488 name_index,
489 acc_flags
490 })
491 )
492);
493
494named!(
495 code_exception<attributes::CodeException>,
496 do_parse!(
497 start_pc: be_u16
498 >> end_pc: be_u16
499 >> handler_pc: be_u16
500 >> catch_type: be_u16
501 >> (attributes::CodeException {
502 start_pc,
503 end_pc,
504 handler_pc,
505 catch_type
506 })
507 )
508);
509
510named_args!(attr_sized(tag: AttrTag, self_len: usize, cp: ConstantPool)<AttributeType>, switch!(value!(tag),
511 AttrTag::ConstantValue => do_parse!(
512 constant_value_index: be_u16 >>
513 (AttributeType::ConstantValue {constant_value_index})
514 ) |
515 AttrTag::Code => do_parse!(
516 max_stack: be_u16 >>
517 max_locals: be_u16 >>
518 len: be_u32 >>
519 code: take!(len) >> exception_count: be_u16 >>
521 exceptions: count!(code_exception, exception_count as usize) >>
522 attrs: call!(attr_type_vec, cp) >>
523 (AttributeType::Code(attributes::Code {
524 max_stack,
525 max_locals,
526 code: Arc::new(Vec::from(code)),
527 exceptions,
528 attrs,
529 }))
530 ) |
531 AttrTag::StackMapTable => do_parse!(
532 frame_count: be_u16 >>
533 frames: count!(stack_map_frame, frame_count as usize) >>
534 (AttributeType::StackMapTable { entries: frames })
535 ) |
536 AttrTag::Exceptions => do_parse!(
537 exception_count: be_u16 >>
538 exceptions: count!(be_u16, exception_count as usize) >>
539 (AttributeType::Exceptions { exceptions })
540 ) |
541 AttrTag::InnerClasses => do_parse!(
542 class_count: be_u16 >>
543 classes: count!(inner_class, class_count as usize) >>
544 (AttributeType::InnerClasses { classes })
545 ) |
546 AttrTag::EnclosingMethod => do_parse!(
547 em: enclosing_method >>
548 (AttributeType::EnclosingMethod { em })
549 ) |
550 AttrTag::Synthetic => value!(AttributeType::Synthetic) |
551 AttrTag::Signature => do_parse!(
552 signature_index: be_u16 >>
553 (AttributeType::Signature { signature_index })
554 ) |
555 AttrTag::SourceFile => do_parse!(
556 source_file_index: be_u16 >>
557 (AttributeType::SourceFile { source_file_index })
558 ) |
559 AttrTag::SourceDebugExtension => do_parse!(
560 debug_extension: take!(self_len) >>
561 (AttributeType::SourceDebugExtension { debug_extension: Arc::new(Vec::from(debug_extension)) })
562 ) |
563 AttrTag::LineNumberTable => do_parse!(
564 line_count: be_u16 >>
565 lines: count!(line_number, line_count as usize) >>
566 (AttributeType::LineNumberTable { tables: lines })
567 ) |
568 AttrTag::LocalVariableTable => do_parse!(
569 variable_count: be_u16 >>
570 variables: count!(local_variable, variable_count as usize) >>
571 (AttributeType::LocalVariableTable { tables: variables })
572 ) |
573 AttrTag::LocalVariableTypeTable => do_parse!(
574 variable_count: be_u16 >>
575 variables: count!(local_variable, variable_count as usize) >>
576 (AttributeType::LocalVariableTypeTable { tables: variables })
577 ) |
578 AttrTag::Deprecated => value!(AttributeType::Deprecated) |
579 AttrTag::RuntimeVisibleAnnotations => do_parse!(
580 raw: peek!(take!(self_len)) >>
581 annotation_count: be_u16 >>
582 annotations: count!(call!(annotation_entry, cp.clone()), annotation_count as usize) >>
583 (AttributeType::RuntimeVisibleAnnotations {raw: Arc::new(Vec::from(raw)), annotations})
584 ) |
585 AttrTag::RuntimeInvisibleAnnotations => do_parse!(
586 raw: peek!(take!(self_len)) >>
587 annotation_count: be_u16 >>
588 annotations: count!(call!(annotation_entry, cp.clone()), annotation_count as usize) >>
589 (AttributeType::RuntimeInvisibleAnnotations {raw: Arc::new(Vec::from(raw)), annotations})
590 ) |
591 AttrTag::RuntimeVisibleParameterAnnotations => do_parse!(
592 raw: peek!(take!(self_len)) >>
593 annotation_count: be_u16 >>
594 annotations: count!(call!(annotation_entry, cp.clone()), annotation_count as usize) >>
595 (AttributeType::RuntimeVisibleParameterAnnotations {raw: Arc::new(Vec::from(raw)), annotations})
596 ) |
597 AttrTag::RuntimeInvisibleParameterAnnotations => do_parse!(
598 raw: peek!(take!(self_len)) >>
599 annotation_count: be_u16 >>
600 annotations: count!(call!(annotation_entry, cp.clone()), annotation_count as usize) >>
601 (AttributeType::RuntimeInvisibleParameterAnnotations {raw: Arc::new(Vec::from(raw)), annotations})
602 ) |
603 AttrTag::RuntimeVisibleTypeAnnotations => do_parse!(
604 raw: peek!(take!(self_len)) >>
605 annotation_count: be_u16 >>
606 annotations: count!(call!(type_annotation, cp.clone()), annotation_count as usize) >>
607 (AttributeType::RuntimeVisibleTypeAnnotations {raw: Arc::new(Vec::from(raw)), annotations})
608 ) |
609 AttrTag::RuntimeInvisibleTypeAnnotations => do_parse!(
610 raw: peek!(take!(self_len)) >>
611 annotation_count: be_u16 >>
612 annotations: count!(call!(type_annotation, cp.clone()), annotation_count as usize) >>
613 (AttributeType::RuntimeInvisibleTypeAnnotations {raw: Arc::new(Vec::from(raw)), annotations})
614 ) |
615 AttrTag::AnnotationDefault => do_parse!(
616 raw: peek!(take!(self_len)) >>
617 default_value: call!(element_value_type, cp) >>
618 (AttributeType::AnnotationDefault {raw: Arc::new(Vec::from(raw)), default_value})
619 ) |
620 AttrTag::BootstrapMethods => do_parse!(
621 method_count: be_u16 >>
622 methods: count!(bootstrap_method, method_count as usize) >>
623 (AttributeType::BootstrapMethods {n:method_count, methods})
624 ) |
625 AttrTag::MethodParameters => do_parse!(
626 parameter_count: be_u8 >>
627 parameters: count!(method_parameter, parameter_count as usize) >>
628 (AttributeType::MethodParameters {parameters})
629 ) |
630 AttrTag::Unknown => do_parse!(
631 _data: take!(self_len) >>
632 (AttributeType::Unknown)
633 )
634));
635
636named_args!(attr_tag(cp: ConstantPool)<AttrTag>, do_parse!(
637 name_index: be_u16 >>
638 name: value!(constant_pool::get_utf8(&cp, name_index as usize).expect("Missing name")) >>
639 inner: value!(AttrTag::from(name.as_slice())) >>
640 (inner)
641));
642
643named_args!(attr_type(cp: ConstantPool)<AttributeType>, do_parse!(
644 tag: call!(attr_tag, cp.clone()) >>
645 length: be_u32 >>
646 attr: call!(attr_sized, tag, length as usize, cp) >>
647 (attr)
648));
649
650named_args!(attr_type_vec(cp: ConstantPool)<Vec<AttributeType>>, do_parse!(
651 attrs_count: be_u16 >>
652 attrs: count!(call!(attr_type, cp.clone()), attrs_count as usize) >>
653 (attrs)
654));
655
656named_args!(field(cp: ConstantPool)<FieldInfo>, do_parse!(
657 acc_flags: be_u16 >>
658 name_index: be_u16 >>
659 desc_index: be_u16 >>
660 attrs: call!(attr_type_vec, cp) >>
661 (FieldInfo {
662 acc_flags,
663 name_index,
664 desc_index,
665 attrs,
666 })
667));
668
669named_args!(method_info(cp: ConstantPool)<MethodInfo>, do_parse!(
670 acc_flags: be_u16 >>
671 name_index: be_u16 >>
672 desc_index: be_u16 >>
673 attrs: call!(attr_type_vec, cp) >>
674 (MethodInfo {
675 acc_flags,
676 name_index,
677 desc_index,
678 attrs,
679 })
680));
681
682named!(
683 class_file<ClassFile>,
684 do_parse!(
685 _magic: tag!(b"\xCA\xFE\xBA\xBE")
686 >> version: version
687 >> cp: constant_pool
688 >> acc_flags: be_u16
689 >> this_class: be_u16
690 >> super_class: be_u16
691 >> interfaces_count: be_u16
692 >> interfaces: count!(be_u16, interfaces_count as usize)
693 >> fields_count: be_u16
694 >> fields: count!(call!(field, cp.clone()), fields_count as usize)
695 >> method_count: be_u16
696 >> methods: count!(call!(method_info, cp.clone()), method_count as usize)
697 >> attrs: call!(attr_type_vec, cp.clone())
698 >> (ClassFile {
699 version,
700 cp: cp.clone(),
701 acc_flags,
702 this_class,
703 super_class,
704 interfaces,
705 fields,
706 methods,
707 attrs
708 })
709 )
710);
711
712pub fn parse(input: &[u8]) -> nom::IResult<&[u8], ClassFile> {
713 class_file(input)
714}