java_asm/impls/node/r/
attr_reader.rs

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    /// converts jvms attributes [JvmsAttribute] to node attributes [NodeAttribute]
27    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}