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 MethodAttribute {
83 pub fn kind(&self) -> AttributeKind {
84 match self {
85 Self::Shared(attr) => attr.kind(),
86 Self::Code { .. } => AttributeKind::Code,
87 Self::Exceptions { .. } => AttributeKind::Exceptions,
88 Self::RuntimeVisibleParameterAnnotations { .. } => {
89 AttributeKind::RuntimeVisibleParameterAnnotations
90 }
91 Self::RuntimeInvisibleParameterAnnotations { .. } => {
92 AttributeKind::RuntimeInvisibleParameterAnnotations
93 }
94 Self::AnnotationsDefault { .. } => AttributeKind::AnnotationDefault,
95 Self::MethodParameters { .. } => AttributeKind::MethodParameters,
96 }
97 }
98}
99
100impl<'a> MethodAttribute {
101 pub(crate) fn read(
102 pool: &ConstantPool,
103 cursor: &mut ByteCursor<'a>,
104 ) -> Result<Self, ClassFormatErr> {
105 let attr_name_idx = cursor.u16()?;
106 let _attribute_length = cursor.u32()? as usize;
107
108 let attribute_kind = AttributeKind::try_from(pool.get_utf8(&attr_name_idx)?)?;
109 match attribute_kind {
110 AttributeKind::Code => Ok(MethodAttribute::Code {
111 attr_name_idx,
112 code_attr: CodeAttribute::read(pool, cursor)?,
113 }),
114 AttributeKind::RuntimeVisibleAnnotations
115 | AttributeKind::Synthetic
116 | AttributeKind::Deprecated
117 | AttributeKind::RuntimeInvisibleAnnotations
118 | AttributeKind::Signature => Ok(MethodAttribute::Shared(SharedAttribute::read(
119 attr_name_idx,
120 attribute_kind,
121 cursor,
122 )?)),
123 AttributeKind::MethodParameters => {
124 let parameters_count = cursor.u8()? as usize;
125 let mut params = Vec::with_capacity(parameters_count);
126 for _ in 0..parameters_count {
127 params.push(MethodParameterEntry::new(cursor.u16()?, cursor.u16()?));
128 }
129 Ok(MethodAttribute::MethodParameters {
130 attr_name_idx,
131 params,
132 })
133 }
134 AttributeKind::Exceptions => {
135 let number_of_exceptions = cursor.u16()?;
136 let mut exception_idx_table = Vec::with_capacity(number_of_exceptions as usize);
137 for _ in 0..number_of_exceptions {
138 exception_idx_table.push(cursor.u16()?);
139 }
140 Ok(MethodAttribute::Exceptions {
141 attr_name_idx,
142 exception_idx_table,
143 })
144 }
145 AttributeKind::RuntimeVisibleParameterAnnotations => {
146 let number_of_parameters = cursor.u8()?;
147 let mut parameter_annotations = Vec::with_capacity(number_of_parameters as usize);
148 for _ in 0..number_of_parameters {
149 let num_annotations = cursor.u16()?;
150 let mut annotations = Vec::with_capacity(num_annotations as usize);
151 for _ in 0..num_annotations {
152 annotations.push(Annotation::read(cursor)?);
153 }
154 parameter_annotations.push(ParameterAnnotations { annotations });
155 }
156 Ok(MethodAttribute::RuntimeVisibleParameterAnnotations {
157 attr_name_idx,
158 annotations: parameter_annotations,
159 })
160 }
161 AttributeKind::RuntimeInvisibleParameterAnnotations => {
162 let number_of_parameters = cursor.u8()?;
163 let mut parameter_annotations = Vec::with_capacity(number_of_parameters as usize);
164 for _ in 0..number_of_parameters {
165 let num_annotations = cursor.u16()?;
166 let mut annotations = Vec::with_capacity(num_annotations as usize);
167 for _ in 0..num_annotations {
168 annotations.push(Annotation::read(cursor)?);
169 }
170 parameter_annotations.push(ParameterAnnotations { annotations });
171 }
172 Ok(MethodAttribute::RuntimeInvisibleParameterAnnotations {
173 attr_name_idx,
174 annotations: parameter_annotations,
175 })
176 }
177 other => unimplemented!("Method attribute {:?} not implemented", other),
178 }
179 }
180}
181
182impl<'a> CodeAttribute {
183 pub(crate) fn read(
184 pool: &ConstantPool,
185 cursor: &mut ByteCursor<'a>,
186 ) -> Result<Self, ClassFormatErr> {
187 let max_stack = cursor.u16()?;
188 let max_locals = cursor.u16()?;
189 let code_length = cursor.u32()? as usize;
190
191 let mut code = vec![0u8; code_length];
192 cursor.read_exact(&mut code)?;
193
194 let exception_table_length = cursor.u16()? as usize;
195 let mut exception_table = Vec::with_capacity(exception_table_length);
196 for _ in 0..exception_table_length {
197 exception_table.push(ExceptionTableEntry {
198 start_pc: cursor.u16()?,
199 end_pc: cursor.u16()?,
200 handler_pc: cursor.u16()?,
201 catch_type: cursor.u16()?,
202 });
203 }
204
205 let attributes_count = cursor.u16()? as usize;
206 let mut attributes = Vec::with_capacity(attributes_count);
207 for _ in 0..attributes_count {
208 attributes.push(CodeAttributeInfo::read(pool, cursor)?);
209 }
210
211 Ok(Self {
212 max_stack,
213 max_locals,
214 code,
215 exception_table,
216 attributes,
217 })
218 }
219}