lvm_class/attribute/method/
mod.rs1use crate::ClassFormatErr;
2use crate::attribute::{Annotation, AttributeKind, SharedAttribute};
3use crate::constant_pool::ConstantPool;
4use common::utils::cursor::ByteCursor;
5
6pub mod code;
7
8pub use code::{
9 CodeAttributeInfo, LineNumberEntry, LocalVariableEntry, LocalVariableTypeEntry, StackMapFrame,
10 VerificationTypeInfo, VerificationTypeTag,
11};
12
13#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct ExceptionTableEntry {
16 pub start_pc: u16,
17 pub end_pc: u16,
18 pub handler_pc: u16,
19 pub catch_type: u16,
20}
21
22#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct CodeAttribute {
25 pub max_stack: u16,
26 pub max_locals: u16,
27 pub code: Vec<u8>,
28 pub exception_table: Vec<ExceptionTableEntry>,
29 pub attributes: Vec<CodeAttributeInfo>,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct MethodParameterEntry {
34 pub name_index: u16,
35 pub access_flags: u16,
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct ParameterAnnotations {
41 pub annotations: Vec<Annotation>,
42}
43
44#[derive(Debug, Clone, PartialEq, Eq)]
46pub enum MethodAttribute {
47 Shared(SharedAttribute),
48 Code(CodeAttribute),
49 Exceptions(Vec<u16>),
50 RuntimeVisibleParameterAnnotations(Vec<ParameterAnnotations>),
51 RuntimeInvisibleParameterAnnotations(Vec<ParameterAnnotations>),
52 AnnotationsDefault,
53 MethodParameters(Vec<MethodParameterEntry>),
54}
55
56impl MethodParameterEntry {
57 pub(crate) fn new(name_index: u16, access_flags: u16) -> Self {
58 Self {
59 name_index,
60 access_flags,
61 }
62 }
63}
64
65impl<'a> MethodAttribute {
66 pub(crate) fn read(
67 pool: &ConstantPool,
68 cursor: &mut ByteCursor<'a>,
69 ) -> Result<Self, ClassFormatErr> {
70 let attribute_name_index = cursor.u16()?;
71 let _attribute_length = cursor.u32()? as usize;
72
73 let attribute_kind = AttributeKind::try_from(pool.get_utf8(&attribute_name_index)?)?;
74 match attribute_kind {
75 AttributeKind::Code => Ok(MethodAttribute::Code(CodeAttribute::read(pool, cursor)?)),
76 AttributeKind::RuntimeVisibleAnnotations
77 | AttributeKind::Synthetic
78 | AttributeKind::Deprecated
79 | AttributeKind::RuntimeInvisibleAnnotations
80 | AttributeKind::Signature => Ok(MethodAttribute::Shared(SharedAttribute::read(
81 attribute_kind,
82 cursor,
83 )?)),
84 AttributeKind::MethodParameters => {
85 let parameters_count = cursor.u8()? as usize;
86 let mut parameters = Vec::with_capacity(parameters_count);
87 for _ in 0..parameters_count {
88 parameters.push(MethodParameterEntry::new(cursor.u16()?, cursor.u16()?));
89 }
90 Ok(MethodAttribute::MethodParameters(parameters))
91 }
92 AttributeKind::Exceptions => {
93 let number_of_exceptions = cursor.u16()?;
94 let mut exception_index_table = Vec::with_capacity(number_of_exceptions as usize);
95 for _ in 0..number_of_exceptions {
96 exception_index_table.push(cursor.u16()?);
97 }
98 Ok(MethodAttribute::Exceptions(exception_index_table))
99 }
100 AttributeKind::RuntimeVisibleParameterAnnotations => {
101 let number_of_parameters = cursor.u8()?;
102 let mut parameter_annotations = Vec::with_capacity(number_of_parameters as usize);
103 for _ in 0..number_of_parameters {
104 let num_annotations = cursor.u16()?;
105 let mut annotations = Vec::with_capacity(num_annotations as usize);
106 for _ in 0..num_annotations {
107 annotations.push(Annotation::read(cursor)?);
108 }
109 parameter_annotations.push(ParameterAnnotations { annotations });
110 }
111 Ok(MethodAttribute::RuntimeVisibleParameterAnnotations(
112 parameter_annotations,
113 ))
114 }
115 AttributeKind::RuntimeInvisibleParameterAnnotations => {
116 let number_of_parameters = cursor.u8()?;
117 let mut parameter_annotations = Vec::with_capacity(number_of_parameters as usize);
118 for _ in 0..number_of_parameters {
119 let num_annotations = cursor.u16()?;
120 let mut annotations = Vec::with_capacity(num_annotations as usize);
121 for _ in 0..num_annotations {
122 annotations.push(Annotation::read(cursor)?);
123 }
124 parameter_annotations.push(ParameterAnnotations { annotations });
125 }
126 Ok(MethodAttribute::RuntimeInvisibleParameterAnnotations(
127 parameter_annotations,
128 ))
129 }
130 other => unimplemented!("Method attribute {:?} not implemented", other),
131 }
132 }
133}
134
135impl<'a> CodeAttribute {
136 pub(crate) fn read(
137 pool: &ConstantPool,
138 cursor: &mut ByteCursor<'a>,
139 ) -> Result<Self, ClassFormatErr> {
140 let max_stack = cursor.u16()?;
141 let max_locals = cursor.u16()?;
142 let code_length = cursor.u32()? as usize;
143
144 let mut code = vec![0u8; code_length];
145 cursor.read_exact(&mut code)?;
146
147 let exception_table_length = cursor.u16()? as usize;
148 let mut exception_table = Vec::with_capacity(exception_table_length);
149 for _ in 0..exception_table_length {
150 exception_table.push(ExceptionTableEntry {
151 start_pc: cursor.u16()?,
152 end_pc: cursor.u16()?,
153 handler_pc: cursor.u16()?,
154 catch_type: cursor.u16()?,
155 });
156 }
157
158 let attributes_count = cursor.u16()? as usize;
159 let mut attributes = Vec::with_capacity(attributes_count);
160 for _ in 0..attributes_count {
161 attributes.push(CodeAttributeInfo::read(pool, cursor)?);
162 }
163
164 Ok(Self {
165 max_stack,
166 max_locals,
167 code,
168 exception_table,
169 attributes,
170 })
171 }
172}