classfile-parser 0.3.4

A parser for Java Class files written in rust
Documentation
use nom::{be_u16, be_u32, be_u8, Err, ErrorKind};

use attribute_info::types::StackMapFrame::*;
use attribute_info::*;

pub fn attribute_parser(input: &[u8]) -> Result<(&[u8], AttributeInfo), Err<&[u8]>> {
    do_parse!(
        input,
        attribute_name_index: be_u16
            >> attribute_length: be_u32
            >> info: take!(attribute_length)
            >> (AttributeInfo {
                attribute_name_index: attribute_name_index,
                attribute_length: attribute_length,
                info: info.to_owned(),
            })
    )
}

pub fn exception_entry_parser(input: &[u8]) -> Result<(&[u8], ExceptionEntry), Err<&[u8]>> {
    do_parse!(
        input,
        start_pc: be_u16
            >> end_pc: be_u16
            >> handler_pc: be_u16
            >> catch_type: be_u16
            >> (ExceptionEntry {
                start_pc: start_pc,
                end_pc: end_pc,
                handler_pc: handler_pc,
                catch_type: catch_type,
            })
    )
}

pub fn code_attribute_parser(input: &[u8]) -> Result<(&[u8], CodeAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        max_stack: be_u16
            >> max_locals: be_u16
            >> code_length: be_u32
            >> code: take!(code_length)
            >> exception_table_length: be_u16
            >> exception_table: count!(exception_entry_parser, exception_table_length as usize)
            >> attributes_count: be_u16
            >> attributes: count!(attribute_parser, attributes_count as usize)
            >> (CodeAttribute {
                max_stack: max_stack,
                max_locals: max_locals,
                code_length: code_length,
                code: code.to_owned(),
                exception_table_length: exception_table_length,
                exception_table: exception_table,
                attributes_count: attributes_count,
                attributes: attributes,
            })
    )
}

fn same_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    value!(input, SameFrame { frame_type })
}

fn verification_type(v: u8) -> Option<VerificationTypeInfo> {
    use self::VerificationTypeInfo::*;
    match v {
        0 => Some(Top),
        1 => Some(Integer),
        2 => Some(Float),
        3 => Some(Double),
        4 => Some(Long),
        5 => Some(Null),
        6 => Some(UninitializedThis),
        7 => Some(Object),
        8 => Some(Uninitialized),
        _ => None,
    }
}

fn verification_type_parser(input: &[u8]) -> Result<(&[u8], VerificationTypeInfo), Err<&[u8]>> {
    match verification_type(input[0]) {
        Some(x) => Result::Ok((&input[1..], x)),
        _ => Result::Err(Err::Error(error_position!(input, ErrorKind::Custom(1)))),
    }
}

fn same_locals_1_stack_item_frame_parser(
    input: &[u8],
    frame_type: u8,
) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        stack: verification_type_parser >> (SameLocals1StackItemFrame { frame_type, stack })
    )
}

fn same_locals_1_stack_item_frame_extended_parser(
    input: &[u8],
    frame_type: u8,
) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> stack: verification_type_parser
            >> (SameLocals1StackItemFrameExtended {
                frame_type,
                offset_delta,
                stack
            })
    )
}

fn chop_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> (ChopFrame {
                frame_type,
                offset_delta
            })
    )
}

fn same_frame_extended_parser(
    input: &[u8],
    frame_type: u8,
) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> (SameFrameExtended {
                frame_type,
                offset_delta
            })
    )
}

fn append_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> locals: count!(verification_type_parser, (frame_type - 251) as usize)
            >> (AppendFrame {
                frame_type,
                offset_delta,
                locals
            })
    )
}

fn full_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> number_of_locals: be_u16
            >> locals: count!(verification_type_parser, number_of_locals as usize)
            >> number_of_stack_items: be_u16
            >> stack: count!(verification_type_parser, number_of_stack_items as usize)
            >> (FullFrame {
                frame_type,
                offset_delta,
                number_of_locals,
                locals,
                number_of_stack_items,
                stack,
            })
    )
}

fn stack_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    match frame_type {
        0...63 => same_frame_parser(input, frame_type),
        64...127 => same_locals_1_stack_item_frame_parser(input, frame_type),
        247 => same_locals_1_stack_item_frame_extended_parser(input, frame_type),
        248...250 => chop_frame_parser(input, frame_type),
        251 => same_frame_extended_parser(input, frame_type),
        252...254 => append_frame_parser(input, frame_type),
        255 => full_frame_parser(input, frame_type),
        _ => Result::Err(Err::Error(error_position!(input, ErrorKind::Custom(2)))),
    }
}

fn stack_map_frame_entry_parser(input: &[u8]) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        frame_type: be_u8 >> stack_frame: apply!(stack_frame_parser, frame_type) >> (stack_frame)
    )
}

pub fn stack_map_table_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], StackMapTableAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        number_of_entries: be_u16
            >> entries: count!(stack_map_frame_entry_parser, number_of_entries as usize)
            >> (StackMapTableAttribute {
                number_of_entries,
                entries,
            })
    )
}

pub fn exceptions_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], ExceptionsAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        exception_table_length: be_u16
            >> exception_table: count!(be_u16, exception_table_length as usize)
            >> (ExceptionsAttribute {
                exception_table_length: exception_table_length,
                exception_table: exception_table,
            })
    )
}

pub fn constant_value_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], ConstantValueAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        constant_value_index: be_u16
            >> (ConstantValueAttribute {
                constant_value_index: constant_value_index,
            })
    )
}

fn bootstrap_method_parser(input: &[u8]) -> Result<(&[u8], BootstrapMethod), Err<&[u8]>> {
    do_parse!(
        input,
        bootstrap_method_ref: be_u16
            >> num_bootstrap_arguments: be_u16
            >> bootstrap_arguments: count!(be_u16, num_bootstrap_arguments as usize)
            >> (BootstrapMethod {
                bootstrap_method_ref,
                num_bootstrap_arguments,
                bootstrap_arguments,
            })
    )
}

pub fn bootstrap_methods_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], BootstrapMethodsAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        num_bootstrap_methods: be_u16
            >> bootstrap_methods: count!(bootstrap_method_parser, num_bootstrap_methods as usize)
            >> (BootstrapMethodsAttribute {
                num_bootstrap_methods,
                bootstrap_methods,
            })
    )
}

pub fn sourcefile_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], SourceFileAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        attribute_name_index: be_u16
            >> attribute_length: be_u32
            >> sourcefile_index: be_u16
            >> (SourceFileAttribute {
                attribute_name_index,
                attribute_length,
                sourcefile_index
            })
    )
}