cfsp/parse/
attribute.rs

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}