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