1use std::io::{Cursor, Read};
2
3use byteorder::{BigEndian, ReadBytesExt};
4
5use crate::node::attribute;
6use crate::node::attribute::{
7 Attribute, AttributeInfo, ConstantValue, EnclosingMethod, Exceptions, ModuleMainClass,
8 ModulePackages, NestHost, NestMembers, PermittedSubclasses, Signature, SourceDebugExtension,
9 SourceFile,
10};
11use crate::node::constant::ConstantPool;
12use crate::node::constant::Utf8;
13use crate::parse::attribute::annotation::{
14 annotation_default, runtime_invisible_annotations, runtime_invisible_parameter_annotations,
15 runtime_invisible_type_annotations, runtime_visible_annotations,
16 runtime_visible_parameter_annotations, runtime_visible_type_annotations,
17};
18use crate::parse::attribute::bootstrap_methods::bootstrap_methods;
19use crate::parse::attribute::code::code;
20use crate::parse::attribute::inner_classes::inner_classes;
21use crate::parse::attribute::line_number_table::line_number_table;
22use crate::parse::attribute::local_variable_table::local_variable_table;
23use crate::parse::attribute::local_variable_type_table::local_variable_type_table;
24use crate::parse::attribute::method_parameters::method_parameters;
25use crate::parse::attribute::module::module;
26use crate::parse::attribute::record::record;
27use crate::parse::attribute::stack_map_table::stack_map_table;
28use crate::parse::error::{ParseError, ParseResult};
29use crate::parse::ParsingOption;
30
31mod annotation;
32mod bootstrap_methods;
33mod code;
34mod inner_classes;
35mod line_number_table;
36mod local_variable_table;
37mod local_variable_type_table;
38mod method_parameters;
39mod module;
40mod record;
41mod stack_map_table;
42
43pub(super) fn attribute_info<'input: 'constant_pool, 'constant_pool, R: Read>(
44 input: &'input mut R,
45 constant_pool: &'constant_pool ConstantPool,
46 option: &ParsingOption,
47) -> ParseResult<AttributeInfo> {
48 let attribute_name_index = input.read_u16::<BigEndian>()?;
49 let attribute_len = input.read_u32::<BigEndian>()?;
50 let mut info = vec![0; attribute_len as usize];
51
52 input.read_exact(&mut info)?;
53
54 let attribute = if !option.skip_attribute {
55 if let Some(Ok(attribute_name)) = constant_pool
56 .get_utf8(attribute_name_index)
57 .map(Utf8::string)
58 {
59 let mut info = Cursor::new(&mut info[..]);
60 let attribute = attribute(
61 &mut info,
62 constant_pool,
63 attribute_len,
64 &attribute_name,
65 option,
66 )?;
67
68 let mut remain = vec![];
69 info.read_to_end(&mut remain)?;
70
71 if !remain.is_empty() {
72 return Err(ParseError::Remains(remain.len()));
73 }
74
75 attribute
76 } else {
77 None
78 }
79 } else {
80 None
81 };
82
83 Ok(AttributeInfo {
84 attribute_name_index,
85 attribute_len,
86 info,
87 attribute,
88 })
89}
90
91fn attribute<'input: 'constant_pool, 'constant_pool: 'data, 'data, R: Read>(
92 input: &'input mut R,
93 constant_pool: &'constant_pool ConstantPool,
94 attribute_len: u32,
95 data: &'data str,
96 option: &ParsingOption,
97) -> ParseResult<Option<Attribute>> {
98 let attribute = match data {
99 attribute::CONSTANT_VALUE => constant_value(input)?,
100 attribute::CODE => code(input, constant_pool, option)?,
101 attribute::STACK_MAP_TABLE => stack_map_table(input)?,
102 attribute::EXCEPTIONS => exceptions(input)?,
103 attribute::INNER_CLASSES => inner_classes(input)?,
104 attribute::ENCLOSING_METHOD => enclosing_method(input)?,
105 attribute::SYNTHETIC => Some(Attribute::Synthetic),
106 attribute::SIGNATURE => signature(input)?,
107 attribute::SOURCE_FILE => source_file(input)?,
108 attribute::SOURCE_DEBUG_EXTENSION => source_debug_extension(input, attribute_len)?,
109 attribute::LINE_NUMBER_TABLE => line_number_table(input)?,
110 attribute::LOCAL_VARIABLE_TABLE => local_variable_table(input)?,
111 attribute::LOCAL_VARIABLE_TYPE_TABLE => local_variable_type_table(input)?,
112 attribute::DEPRECATED => Some(Attribute::Deprecate),
113 attribute::RUNTIME_VISIBLE_ANNOTATIONS => runtime_visible_annotations(input)?,
114 attribute::RUNTIME_INVISIBLE_ANNOTATIONS => runtime_invisible_annotations(input)?,
115 attribute::RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS => {
116 runtime_visible_parameter_annotations(input)?
117 }
118 attribute::RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS => {
119 runtime_invisible_parameter_annotations(input)?
120 }
121 attribute::RUNTIME_VISIBLE_TYPE_ANNOTATIONS => runtime_visible_type_annotations(input)?,
122 attribute::RUNTIME_INVISIBLE_TYPE_ANNOTATIONS => runtime_invisible_type_annotations(input)?,
123 attribute::ANNOTATION_DEFAULT => annotation_default(input)?,
124 attribute::BOOTSTRAP_METHODS => bootstrap_methods(input)?,
125 attribute::METHOD_PARAMETERS => method_parameters(input)?,
126 attribute::MODULE => module(input)?,
127 attribute::MODULE_PACKAGES => module_packages(input)?,
128 attribute::MODULE_MAIN_CLASS => module_main_class(input)?,
129 attribute::NEST_HOST => nest_host(input)?,
130 attribute::NEST_MEMBERS => nest_members(input)?,
131 attribute::RECORD => record(input, constant_pool, option)?,
132 attribute::PERMITTED_SUBCLASSES => permitted_subclasses(input)?,
133 _ => None,
134 };
135
136 Ok(attribute)
137}
138
139#[inline]
140fn constant_value<R: Read>(input: &mut R) -> ParseResult<Option<Attribute>> {
141 let constant_value_index = input.read_u16::<BigEndian>()?;
142
143 Ok(Some(Attribute::ConstantValue(ConstantValue {
144 constant_value_index,
145 })))
146}
147
148#[inline]
149fn exceptions<R: Read>(input: &mut R) -> ParseResult<Option<Attribute>> {
150 let number_of_exceptions = input.read_u16::<BigEndian>()?;
151 let mut exception_index_table = vec![0; number_of_exceptions as usize];
152
153 for i in 0..number_of_exceptions {
154 exception_index_table[i as usize] = input.read_u16::<BigEndian>()?;
155 }
156
157 Ok(Some(Attribute::Exceptions(Exceptions {
158 number_of_exceptions,
159 exception_index_table,
160 })))
161}
162
163#[inline]
164fn enclosing_method<R: Read>(input: &mut R) -> ParseResult<Option<Attribute>> {
165 let class_index = input.read_u16::<BigEndian>()?;
166 let method_index = input.read_u16::<BigEndian>()?;
167
168 Ok(Some(Attribute::EnclosingMethod(EnclosingMethod {
169 class_index,
170 method_index,
171 })))
172}
173
174#[inline]
175fn signature<R: Read>(input: &mut R) -> ParseResult<Option<Attribute>> {
176 let signature_index = input.read_u16::<BigEndian>()?;
177
178 Ok(Some(Attribute::Signature(Signature { signature_index })))
179}
180
181#[inline]
182fn source_file<R: Read>(input: &mut R) -> ParseResult<Option<Attribute>> {
183 let source_file_index = input.read_u16::<BigEndian>()?;
184
185 Ok(Some(Attribute::SourceFile(SourceFile {
186 source_file_index,
187 })))
188}
189
190#[inline]
191fn source_debug_extension<R: Read>(
192 input: &mut R,
193 attribute_len: u32,
194) -> ParseResult<Option<Attribute>> {
195 let mut debug_extension = vec![0; attribute_len as usize];
196
197 input.read_exact(&mut debug_extension)?;
198
199 Ok(Some(Attribute::SourceDebugExtension(
200 SourceDebugExtension { debug_extension },
201 )))
202}
203
204#[inline]
205fn module_packages<R: Read>(input: &mut R) -> ParseResult<Option<Attribute>> {
206 let package_count = input.read_u16::<BigEndian>()?;
207 let mut package_index = vec![0; package_count as usize];
208
209 for i in 0..package_count {
210 package_index[i as usize] = input.read_u16::<BigEndian>()?;
211 }
212
213 Ok(Some(Attribute::ModulePackages(ModulePackages {
214 package_count,
215 package_index,
216 })))
217}
218
219#[inline]
220fn module_main_class<R: Read>(input: &mut R) -> ParseResult<Option<Attribute>> {
221 let main_class_index = input.read_u16::<BigEndian>()?;
222
223 Ok(Some(Attribute::ModuleMainClass(ModuleMainClass {
224 main_class_index,
225 })))
226}
227
228#[inline]
229fn nest_host<R: Read>(input: &mut R) -> ParseResult<Option<Attribute>> {
230 let host_class_index = input.read_u16::<BigEndian>()?;
231
232 Ok(Some(Attribute::NestHost(NestHost { host_class_index })))
233}
234
235#[inline]
236fn nest_members<R: Read>(input: &mut R) -> ParseResult<Option<Attribute>> {
237 let number_of_classes = input.read_u16::<BigEndian>()?;
238 let mut classes = vec![0; number_of_classes as usize];
239
240 for i in 0..number_of_classes {
241 classes[i as usize] = input.read_u16::<BigEndian>()?;
242 }
243
244 Ok(Some(Attribute::NestMembers(NestMembers {
245 number_of_classes,
246 classes,
247 })))
248}
249
250#[inline]
251fn permitted_subclasses<R: Read>(input: &mut R) -> ParseResult<Option<Attribute>> {
252 let number_of_classes = input.read_u16::<BigEndian>()?;
253 let mut classes = vec![0; number_of_classes as usize];
254
255 for i in 0..number_of_classes {
256 classes[i as usize] = input.read_u16::<BigEndian>()?;
257 }
258
259 Ok(Some(Attribute::PermittedSubclasses(PermittedSubclasses {
260 number_of_classes,
261 classes,
262 })))
263}