classfile-parser 0.3.2

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

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

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})
    )
}