lvm_class/attribute/method/
mod.rs1use crate::ClassFormatErr;
2use crate::attribute::{Annotation, AttributeKind, SharedAttribute};
3use crate::constant_pool::ConstantPool;
4use lvm_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 {
49 attr_name_idx: u16,
50 code_attr: CodeAttribute,
51 },
52 Exceptions {
53 attr_name_idx: u16,
54 exception_idx_table: Vec<u16>,
55 },
56 RuntimeVisibleParameterAnnotations {
57 attr_name_idx: u16,
58 annotations: Vec<ParameterAnnotations>,
59 },
60 RuntimeInvisibleParameterAnnotations {
61 attr_name_idx: u16,
62 annotations: Vec<ParameterAnnotations>,
63 },
64 AnnotationsDefault {
65 attr_name_idx: u16,
66 },
67 MethodParameters {
68 attr_name_idx: u16,
69 params: Vec<MethodParameterEntry>,
70 },
71}
72
73impl MethodParameterEntry {
74 pub(crate) fn new(name_index: u16, access_flags: u16) -> Self {
75 Self {
76 name_index,
77 access_flags,
78 }
79 }
80}
81
82impl<'a> MethodAttribute {
83 pub(crate) fn read(
84 pool: &ConstantPool,
85 cursor: &mut ByteCursor<'a>,
86 ) -> Result<Self, ClassFormatErr> {
87 let attr_name_idx = cursor.u16()?;
88 let _attribute_length = cursor.u32()? as usize;
89
90 let attribute_kind = AttributeKind::try_from(pool.get_utf8(&attr_name_idx)?)?;
91 match attribute_kind {
92 AttributeKind::Code => Ok(MethodAttribute::Code {
93 attr_name_idx,
94 code_attr: CodeAttribute::read(pool, cursor)?,
95 }),
96 AttributeKind::RuntimeVisibleAnnotations
97 | AttributeKind::Synthetic
98 | AttributeKind::Deprecated
99 | AttributeKind::RuntimeInvisibleAnnotations
100 | AttributeKind::Signature => Ok(MethodAttribute::Shared(SharedAttribute::read(
101 attr_name_idx,
102 attribute_kind,
103 cursor,
104 )?)),
105 AttributeKind::MethodParameters => {
106 let parameters_count = cursor.u8()? as usize;
107 let mut params = Vec::with_capacity(parameters_count);
108 for _ in 0..parameters_count {
109 params.push(MethodParameterEntry::new(cursor.u16()?, cursor.u16()?));
110 }
111 Ok(MethodAttribute::MethodParameters {
112 attr_name_idx,
113 params,
114 })
115 }
116 AttributeKind::Exceptions => {
117 let number_of_exceptions = cursor.u16()?;
118 let mut exception_idx_table = Vec::with_capacity(number_of_exceptions as usize);
119 for _ in 0..number_of_exceptions {
120 exception_idx_table.push(cursor.u16()?);
121 }
122 Ok(MethodAttribute::Exceptions {
123 attr_name_idx,
124 exception_idx_table,
125 })
126 }
127 AttributeKind::RuntimeVisibleParameterAnnotations => {
128 let number_of_parameters = cursor.u8()?;
129 let mut parameter_annotations = Vec::with_capacity(number_of_parameters as usize);
130 for _ in 0..number_of_parameters {
131 let num_annotations = cursor.u16()?;
132 let mut annotations = Vec::with_capacity(num_annotations as usize);
133 for _ in 0..num_annotations {
134 annotations.push(Annotation::read(cursor)?);
135 }
136 parameter_annotations.push(ParameterAnnotations { annotations });
137 }
138 Ok(MethodAttribute::RuntimeVisibleParameterAnnotations {
139 attr_name_idx,
140 annotations: parameter_annotations,
141 })
142 }
143 AttributeKind::RuntimeInvisibleParameterAnnotations => {
144 let number_of_parameters = cursor.u8()?;
145 let mut parameter_annotations = Vec::with_capacity(number_of_parameters as usize);
146 for _ in 0..number_of_parameters {
147 let num_annotations = cursor.u16()?;
148 let mut annotations = Vec::with_capacity(num_annotations as usize);
149 for _ in 0..num_annotations {
150 annotations.push(Annotation::read(cursor)?);
151 }
152 parameter_annotations.push(ParameterAnnotations { annotations });
153 }
154 Ok(MethodAttribute::RuntimeInvisibleParameterAnnotations {
155 attr_name_idx,
156 annotations: parameter_annotations,
157 })
158 }
159 other => unimplemented!("Method attribute {:?} not implemented", other),
160 }
161 }
162}
163
164impl<'a> CodeAttribute {
165 pub(crate) fn read(
166 pool: &ConstantPool,
167 cursor: &mut ByteCursor<'a>,
168 ) -> Result<Self, ClassFormatErr> {
169 let max_stack = cursor.u16()?;
170 let max_locals = cursor.u16()?;
171 let code_length = cursor.u32()? as usize;
172
173 let mut code = vec![0u8; code_length];
174 cursor.read_exact(&mut code)?;
175
176 let exception_table_length = cursor.u16()? as usize;
177 let mut exception_table = Vec::with_capacity(exception_table_length);
178 for _ in 0..exception_table_length {
179 exception_table.push(ExceptionTableEntry {
180 start_pc: cursor.u16()?,
181 end_pc: cursor.u16()?,
182 handler_pc: cursor.u16()?,
183 catch_type: cursor.u16()?,
184 });
185 }
186
187 let attributes_count = cursor.u16()? as usize;
188 let mut attributes = Vec::with_capacity(attributes_count);
189 for _ in 0..attributes_count {
190 attributes.push(CodeAttributeInfo::read(pool, cursor)?);
191 }
192
193 Ok(Self {
194 max_stack,
195 max_locals,
196 code,
197 exception_table,
198 attributes,
199 })
200 }
201}