Skip to main content

java_class_rs/
parser.rs

1use nom::{bytes::complete::tag, multi::count, number::complete::be_u16, IResult};
2
3use crate::attribute::parse_attributes;
4use crate::constant_pool::parse_constant_pool;
5use crate::field::parse_field;
6use crate::method::parse_method;
7use crate::types::*;
8
9/// Parse a Java class file from raw bytes.
10///
11/// Returns the remaining unparsed bytes and the parsed `ClassFile`.
12/// Fails if the magic number (0xCAFEBABE) doesn't match or the data is malformed.
13pub fn parse_classfile(input: &[u8]) -> IResult<&[u8], ClassFile> {
14    // Magic number: 0xCAFEBABE
15    let (input, _) = tag(&[0xCA, 0xFE, 0xBA, 0xBE])(input)?;
16
17    let (input, minor_version) = be_u16(input)?;
18    let (input, major_version) = be_u16(input)?;
19
20    let (input, constant_pool_count) = be_u16(input)?;
21    let (input, constant_pool) = parse_constant_pool(input, constant_pool_count)?;
22
23    let (input, access_flags) = be_u16(input)?;
24    let (input, this_class) = be_u16(input)?;
25    let (input, super_class) = be_u16(input)?;
26
27    let (input, interfaces_count) = be_u16(input)?;
28    let (input, interfaces) = count(be_u16, interfaces_count as usize)(input)?;
29
30    let (input, fields_count) = be_u16(input)?;
31    let (input, fields) = count(parse_field, fields_count as usize)(input)?;
32
33    let (input, methods_count) = be_u16(input)?;
34    let (input, methods) = count(parse_method, methods_count as usize)(input)?;
35
36    let (input, attributes) = parse_attributes(input)?;
37
38    Ok((
39        input,
40        ClassFile {
41            minor_version,
42            major_version,
43            constant_pool,
44            access_flags: ClassAccessFlags::from_bits_truncate(access_flags),
45            this_class,
46            super_class,
47            interfaces,
48            fields,
49            methods,
50            attributes,
51        },
52    ))
53}