1use crate::err::{AsmResult, AsmResultOkExt};
2use crate::impls::node::r::node_reader::{ClassNodeContext, ConstPool};
3use crate::jvms::attr::annotation::{AnnotationElementValue, AnnotationInfo};
4use crate::jvms::attr::Attribute as JvmsAttribute;
5use crate::jvms::attr::RecordComponentInfo;
6use crate::jvms::attr::type_annotation::TypeAnnotation;
7use crate::jvms::element::AttributeInfo;
8use crate::node::element::{AnnotationNode, BootstrapMethodAttr, CodeAttribute, EnclosingMethodAttribute, ExceptionTable, InnerClassNode, ParameterNode, RecordComponentNode, TypeAnnotationNode, UnknownAttribute};
9use crate::node::element::Attribute as NodeAttribute;
10use crate::node::values::{AnnotationValue, LocalVariableInfo, LocalVariableTypeInfo, ModuleAttrValue, ModuleExportValue, ModuleOpenValue, ModuleProvidesValue, ModuleRequireValue};
11use crate::impls::{mutf8_to_string, VecEx};
12
13impl ClassNodeContext {
14 pub fn read_class_attrs(&self) -> AsmResult<Vec<(AttributeInfo, NodeAttribute)>> {
15 let jvms_attrs = &self.jvms_file.attributes;
16 let attributes = self.cp.read_attrs(jvms_attrs)?;
17 let mut result = Vec::with_capacity(attributes.len());
18 for (attr_info, attr) in attributes {
19 result.push((attr_info.clone(), attr));
20 }
21 result.ok()
22 }
23}
24
25impl ConstPool {
26 pub fn read_attrs(&self, attrs: &Vec<AttributeInfo>) -> AsmResult<Vec<(AttributeInfo, NodeAttribute)>> {
28 let mut result = Vec::with_capacity(attrs.len());
29 for attr_info in attrs {
30 let attribute = self.read_attr(attr_info)?;
31 result.push((attr_info.clone(), attribute));
32 };
33 Ok(result)
34 }
35
36 pub fn read_attr(&self, attribute_info: &AttributeInfo) -> AsmResult<NodeAttribute> {
37 let attr = match &attribute_info.info {
38 JvmsAttribute::Code {
39 max_stack, max_locals, code, exception_table,
40 attributes: jvms_attributes, ..
41 } => {
42 let exception_table = exception_table.iter().map(|et| {
43 ExceptionTable {
44 start: et.start_pc,
45 end: et.end_pc,
46 handler: et.handler_pc,
47 catch_type: self.read_class_info(et.catch_type).ok(),
48 }
49 }).collect();
50 let mut attributes = vec![];
51 for attr in jvms_attributes {
52 let attribute_info = attr.clone();
53 let attr = self.read_attr(attr)?;
54 attributes.push((attribute_info, attr));
55 }
56 NodeAttribute::Code(CodeAttribute {
57 max_stack: *max_stack,
58 max_locals: *max_locals,
59 code: code.clone(),
60 exception_table,
61 attributes,
62 })
63 },
64 JvmsAttribute::StackMapTable { entries, .. } => NodeAttribute::StackMapTable(entries.clone()),
65 JvmsAttribute::Exceptions { exception_index_table, .. } => {
66 let exceptions = exception_index_table.map_res(|index| self.read_class_info(*index))?;
67 NodeAttribute::Exceptions(exceptions)
68 },
69 JvmsAttribute::InnerClasses { classes, .. } => {
70 let classes = classes.map_res(|inner_class| {
71 let name = self.read_class_info(inner_class.inner_class_info_index)?;
72 let outer_name = self.read_class_info(inner_class.outer_class_info_index).ok();
73 let inner_name = self.read_utf8(inner_class.inner_name_index)?;
74 let access = inner_class.inner_class_access_flags;
75 Ok(InnerClassNode { name, outer_name, inner_name, access })
76 })?;
77 NodeAttribute::InnerClasses(classes)
78 },
79 JvmsAttribute::EnclosingMethod { class_index, method_index } => {
80 let class = self.read_class_info(*class_index)?;
81 let (method_name, method_desc) = self.read_name_and_type(*method_index)?;
82 NodeAttribute::EnclosingMethod(
83 EnclosingMethodAttribute { class, method_name, method_desc })
84 },
85 JvmsAttribute::Synthetic => NodeAttribute::Synthetic,
86 JvmsAttribute::Signature { signature_index } => NodeAttribute::Signature(self.read_utf8(*signature_index)?),
87 JvmsAttribute::SourceFile { sourcefile_index } => NodeAttribute::SourceFile(self.read_utf8(*sourcefile_index)?),
88 JvmsAttribute::SourceDebugExtension { debug_extension } => NodeAttribute::SourceDebugExtension(
89 mutf8_to_string(debug_extension)?,
90 ),
91 JvmsAttribute::LineNumberTable { line_number_table, .. } => {
92 NodeAttribute::LineNumberTable(line_number_table.clone())
93 },
94 JvmsAttribute::LocalVariableTable { local_variable_table, .. } => {
95 let local_variables = local_variable_table.map_res(|local_variable| {
96 let start = local_variable.start_pc;
97 let length = local_variable.length;
98 let name = self.read_utf8(local_variable.name_index)?;
99 let desc = self.read_utf8(local_variable.descriptor_index)?;
100 let index = local_variable.index;
101 Ok(LocalVariableInfo { start, length, name, desc, index })
102 })?;
103 NodeAttribute::LocalVariableTable(local_variables)
104 },
105 JvmsAttribute::LocalVariableTypeTable { local_variable_table, .. } => {
106 let local_variables = local_variable_table.map_res(|local_variable| {
107 let start = local_variable.start_pc;
108 let length = local_variable.length;
109 let name = self.read_utf8(local_variable.name_index)?;
110 let signature = self.read_utf8(local_variable.signature_index)?;
111 let index = local_variable.index;
112 Ok(LocalVariableTypeInfo { start, length, name, signature, index })
113 })?;
114 NodeAttribute::LocalVariableTypeTable(local_variables)
115 },
116 JvmsAttribute::Deprecated => NodeAttribute::Deprecated,
117 JvmsAttribute::RuntimeVisibleAnnotations { annotations, .. } => {
118 let annotations = annotations.map_res(|annotation|
119 self.read_annotation_info(true, annotation))?;
120 NodeAttribute::RuntimeVisibleAnnotations(annotations)
121 },
122 JvmsAttribute::RuntimeInvisibleAnnotations { annotations, .. } => {
123 let annotations = annotations.map_res(|annotation|
124 self.read_annotation_info(false, annotation))?;
125 NodeAttribute::RuntimeInvisibleAnnotations(annotations)
126 },
127 JvmsAttribute::RuntimeVisibleParameterAnnotations { parameter_annotations, .. } => {
128 let parameter_annotations = parameter_annotations.map_res(|parameter|
129 parameter.annotations.map_res(|annotation| self.read_annotation_info(true, annotation)))?;
130 NodeAttribute::RuntimeVisibleParameterAnnotations(parameter_annotations)
131 },
132 JvmsAttribute::RuntimeInvisibleParameterAnnotations { parameter_annotations, .. } => {
133 let parameter_annotations = parameter_annotations.map_res(|parameter|
134 parameter.annotations.map_res(|annotation| self.read_annotation_info(false, annotation)))?;
135 NodeAttribute::RuntimeInvisibleParameterAnnotations(parameter_annotations)
136 },
137 JvmsAttribute::RuntimeVisibleTypeAnnotations { annotations, .. } => {
138 let annotations = annotations.map_res(|annotation|
139 self.read_type_annotation(true, annotation))?;
140 NodeAttribute::RuntimeVisibleTypeAnnotations(annotations)
141 },
142 JvmsAttribute::RuntimeInvisibleTypeAnnotations { annotations, .. } => {
143 let annotations = annotations.map_res(|annotation|
144 self.read_type_annotation(false, annotation))?;
145 NodeAttribute::RuntimeInvisibleTypeAnnotations(annotations)
146 },
147 JvmsAttribute::AnnotationDefault { default_value } => {
148 let value = self.read_annotation_value(true, &default_value.value)?;
149 NodeAttribute::AnnotationDefault(value)
150 },
151 JvmsAttribute::BootstrapMethods { bootstrap_methods, .. } => {
152 let methods = bootstrap_methods.map_res(|method| {
153 let method_handle = self.get_res(method.bootstrap_method_ref)?;
154 let arguments = method.bootstrap_arguments.map_res(|arg| self.get_res(*arg))?;
155 BootstrapMethodAttr { method_handle, arguments }.ok()
156 })?;
157 NodeAttribute::BootstrapMethods(methods)
158 },
159 JvmsAttribute::MethodParameters { parameters, .. } => {
160 let parameters = parameters.map_res(|parameter| {
161 let name = self.read_utf8(parameter.name_index).ok();
162 let access = parameter.access_flags;
163 Ok(ParameterNode { name, access })
164 })?;
165 NodeAttribute::MethodParameters(parameters)
166 },
167 JvmsAttribute::Module {
168 module_name_index, module_flags, module_version_index,
169 requires, exports, opens, uses_index, provides, ..
170 } => {
171 let name = self.read_utf8(*module_name_index)?;
172 let access = *module_flags;
173 let version = self.read_utf8(*module_version_index).ok();
174 let requires = requires.map_res(|require| {
175 let module = self.read_module(require.requires_index)?;
176 let access = require.requires_flags;
177 let version = self.read_utf8(require.requires_version_index).ok();
178 Ok(ModuleRequireValue { module, access, version })
179 })?;
180 let exports = exports.map_res(|export| {
181 let package = self.read_package(export.exports_index)?;
182 let access = export.exports_flags;
183 let modules = export.exports_to_index.map_res(|index| self.read_module(*index))?;
184 Ok(ModuleExportValue { package, access, modules })
185 })?;
186 let opens = opens.map_res(|open| {
187 let package = self.read_package(open.opens_index)?;
188 let access = open.opens_flags;
189 let modules = open.opens_to_index.map_res(|index| self.read_module(*index))?;
190 Ok(ModuleOpenValue { package, access, modules })
191 })?;
192 let uses = uses_index.map_res(|index| self.read_class_info(*index))?;
193 let provides = provides.map_res(|provide| {
194 let service = self.read_class_info(provide.provides_index)?;
195 let providers = provide.provides_with_index.map_res(|index| self.read_class_info(*index))?;
196 Ok(ModuleProvidesValue { service, providers })
197 })?;
198 let attr_value = ModuleAttrValue {
199 name, access, version, requires, exports, opens, uses, provides
200 };
201 NodeAttribute::Module(attr_value)
202 }
203 JvmsAttribute::ModulePackages { package_index, .. } => {
204 let packages = package_index.map_res(|index| self.read_package(*index))?;
205 NodeAttribute::ModulePackages(packages)
206 },
207 JvmsAttribute::ModuleMainClass { main_class_index } => {
208 let main_class = self.read_class_info(*main_class_index)?;
209 NodeAttribute::ModuleMainClass(main_class)
210 },
211 JvmsAttribute::NestHost { host_class_index } => {
212 let host_class = self.read_class_info(*host_class_index)?;
213 NodeAttribute::NestHost(host_class)
214 },
215 JvmsAttribute::NestMembers { classes, .. } => {
216 let classes = classes.map_res(|index| self.read_class_info(*index))?;
217 NodeAttribute::NestMembers(classes)
218 },
219 JvmsAttribute::Record { components, .. } => {
220 let components = components.map_res(|component| {
221 self.read_record(component)
222 })?;
223 NodeAttribute::Record(components)
224 },
225 JvmsAttribute::PermittedSubclasses { classes, .. } => {
226 let classes = classes.map_res(|index| self.read_class_info(*index))?;
227 NodeAttribute::PermittedSubclasses(classes)
228 },
229 _ => NodeAttribute::Unknown(UnknownAttribute {
230 name: self.read_utf8(attribute_info.attribute_name_index)?,
231 origin: attribute_info.info.clone(),
232 }),
233 };
234 Ok(attr)
235 }
236
237 fn read_record(&self, component: &RecordComponentInfo) -> AsmResult<RecordComponentNode> {
238 let name = self.read_utf8(component.name_index)?;
239 let desc = self.read_utf8(component.descriptor_index)?;
240 let mut signature = None;
241 let mut annotations = vec![];
242 let mut type_annotations = vec![];
243 let mut unknown_attrs = vec![];
244 for attr_info in &component.attributes {
245 let attr = self.read_attr(attr_info)?;
246 match attr {
247 NodeAttribute::Signature(s) => signature = Some(s.clone()),
248 NodeAttribute::RuntimeVisibleAnnotations(s) => annotations = s.clone(),
249 NodeAttribute::RuntimeInvisibleAnnotations(s) => annotations = s.clone(),
250 NodeAttribute::RuntimeVisibleTypeAnnotations(s) => type_annotations = s.clone(),
251 NodeAttribute::RuntimeInvisibleTypeAnnotations(s) => type_annotations = s.clone(),
252 NodeAttribute::Unknown(info) => unknown_attrs.push(info),
253 _ => return Err(self.err(format!("unsupported record component attribute: {:?}", attr))),
254 }
255 }
256 Ok(RecordComponentNode {
257 name, desc, signature, annotations, type_annotations, attrs: unknown_attrs,
258 })
259 }
260
261 fn read_type_annotation(&self, visible: bool, type_annotation: &TypeAnnotation) -> AsmResult<TypeAnnotationNode> {
262 let annotation_attr = AnnotationInfo {
263 type_index: type_annotation.type_index,
264 num_element_value_pairs: type_annotation.num_element_value_pairs,
265 element_value_pairs: type_annotation.element_value_pairs.clone(),
266 };
267 let annotation_node = self.read_annotation_info(visible, &annotation_attr)?;
268 Ok(TypeAnnotationNode {
269 visible,
270 target_info: type_annotation.target_info.clone(),
271 target_path: type_annotation.target_path.clone(),
272 annotation_node,
273 })
274 }
275
276 fn read_annotation_info(&self, visible: bool, annotation: &AnnotationInfo) -> AsmResult<AnnotationNode> {
277 let type_name = self.read_class_info(annotation.type_index)?;
278 let values = annotation.element_value_pairs.map_res(|pair| {
279 let element_name = self.read_utf8(pair.element_name_index)?;
280 let value = self.read_annotation_value(visible, &pair.value.value)?;
281 Ok((element_name, value))
282 })?;
283 Ok(AnnotationNode { visible, type_name, values })
284 }
285
286 fn read_annotation_value(&self, visible: bool, annotation: &AnnotationElementValue) -> AsmResult<AnnotationValue> {
287 let value = match annotation {
288 AnnotationElementValue::Const { const_value_index } => {
289 let value = self.get_res(*const_value_index)?;
290 AnnotationValue::Const(value)
291 },
292 AnnotationElementValue::EnumConst { type_name_index, const_name_index } => {
293 let name = self.read_utf8(*type_name_index)?;
294 let value = self.read_utf8(*const_name_index)?;
295 AnnotationValue::Enum(name, value)
296 },
297 AnnotationElementValue::Class { class_info_index } => {
298 let name = self.read_utf8(*class_info_index)?;
299 AnnotationValue::Class(name)
300 },
301 AnnotationElementValue::Annotation { annotation_value } => {
302 let annotation = self.read_annotation_info(visible, annotation_value)?;
303 AnnotationValue::Annotation(annotation)
304 },
305 AnnotationElementValue::Array { values, .. } => {
306 let values = values.map_res(|value|
307 self.read_annotation_value(visible, &value.value))?;
308 AnnotationValue::Array(values)
309 },
310 };
311 Ok(value)
312 }
313
314 pub fn unknown_attr(&self, attribute_info: AttributeInfo) -> AsmResult<UnknownAttribute> {
315 Ok(UnknownAttribute {
316 name: self.read_utf8(attribute_info.attribute_name_index)?,
317 origin: attribute_info.info.clone(),
318 })
319 }
320}