pclass_parser/class_parser/
class.rs

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
23// Const generics still not in stable,
24// idk how to write this fancier without them D:
25// Hope compiler will rewrite this properly
26macro_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            // TODO: Nom error
31            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        //spec 4.4.5
132        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
297// I didn't found a way to turn byte/char/double/float/... boilerplate into a macro(
298named_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) >> // TODO: Parse code in same time?)
520        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}