1use nom::{
2 bytes::complete::take,
3 combinator::{map, success},
4 error::{Error, ErrorKind},
5 multi::count,
6 number::complete::{be_u16, be_u32, be_u8},
7 Err as BaseErr,
8};
9
10use attribute_info::types::StackMapFrame::*;
11use attribute_info::*;
12
13type Err<E> = BaseErr<Error<E>>;
15
16pub fn attribute_parser(input: &[u8]) -> Result<(&[u8], AttributeInfo), Err<&[u8]>> {
17 let (input, attribute_name_index) = be_u16(input)?;
18 let (input, attribute_length) = be_u32(input)?;
19 let (input, info) = take(attribute_length)(input)?;
20 Ok((
21 input,
22 AttributeInfo {
23 attribute_name_index,
24 attribute_length,
25 info: info.to_owned(),
26 },
27 ))
28}
29
30pub fn exception_entry_parser(input: &[u8]) -> Result<(&[u8], ExceptionEntry), Err<&[u8]>> {
31 let (input, start_pc) = be_u16(input)?;
32 let (input, end_pc) = be_u16(input)?;
33 let (input, handler_pc) = be_u16(input)?;
34 let (input, catch_type) = be_u16(input)?;
35 Ok((
36 input,
37 ExceptionEntry {
38 start_pc,
39 end_pc,
40 handler_pc,
41 catch_type,
42 },
43 ))
44}
45
46pub fn code_attribute_parser(input: &[u8]) -> Result<(&[u8], CodeAttribute), Err<&[u8]>> {
47 let (input, max_stack) = be_u16(input)?;
48 let (input, max_locals) = be_u16(input)?;
49 let (input, code_length) = be_u32(input)?;
50 let (input, code) = take(code_length)(input)?;
51 let (input, exception_table_length) = be_u16(input)?;
52 let (input, exception_table) =
53 count(exception_entry_parser, exception_table_length as usize)(input)?;
54 let (input, attributes_count) = be_u16(input)?;
55 let (input, attributes) = count(attribute_parser, attributes_count as usize)(input)?;
56 Ok((
57 input,
58 CodeAttribute {
59 max_stack,
60 max_locals,
61 code_length,
62 code: code.to_owned(),
63 exception_table_length,
64 exception_table,
65 attributes_count,
66 attributes,
67 },
68 ))
69}
70
71pub fn method_parameters_attribute_parser(
72 input: &[u8],
73) -> Result<(&[u8], MethodParametersAttribute), Err<&[u8]>> {
74 let (input, parameters_count) = be_u8(input)?;
75 let (input, parameters) = count(parameters_parser, parameters_count as usize)(input)?;
76 Ok((
77 input,
78 MethodParametersAttribute {
79 parameters_count,
80 parameters,
81 },
82 ))
83}
84
85pub fn parameters_parser(input: &[u8]) -> Result<(&[u8], ParameterAttribute), Err<&[u8]>> {
86 let (input, name_index) = be_u16(input)?;
87 let (input, access_flags) = be_u16(input)?;
88 Ok((
89 input,
90 ParameterAttribute {
91 name_index,
92 access_flags,
93 },
94 ))
95}
96
97fn same_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
98 success(SameFrame { frame_type })(input)
99}
100
101fn verification_type_parser(input: &[u8]) -> Result<(&[u8], VerificationTypeInfo), Err<&[u8]>> {
102 use self::VerificationTypeInfo::*;
103 let v = input[0];
104 let new_input = &input[1..];
105 match v {
106 0 => Ok((new_input, Top)),
107 1 => Ok((new_input, Integer)),
108 2 => Ok((new_input, Float)),
109 3 => Ok((new_input, Double)),
110 4 => Ok((new_input, Long)),
111 5 => Ok((new_input, Null)),
112 6 => Ok((new_input, UninitializedThis)),
113 7 => map(be_u16, |class| Object { class })(new_input),
114 8 => map(be_u16, |offset| Uninitialized { offset })(new_input),
115 _ => Result::Err(Err::Error(error_position!(input, ErrorKind::NoneOf))),
116 }
117}
118
119fn same_locals_1_stack_item_frame_parser(
120 input: &[u8],
121 frame_type: u8,
122) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
123 let (input, stack) = verification_type_parser(input)?;
124 Ok((input, SameLocals1StackItemFrame { frame_type, stack }))
125}
126
127fn same_locals_1_stack_item_frame_extended_parser(
128 input: &[u8],
129 frame_type: u8,
130) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
131 let (input, offset_delta) = be_u16(input)?;
132 let (input, stack) = verification_type_parser(input)?;
133 Ok((
134 input,
135 SameLocals1StackItemFrameExtended {
136 frame_type,
137 offset_delta,
138 stack,
139 },
140 ))
141}
142
143fn chop_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
144 let (input, offset_delta) = be_u16(input)?;
145 Ok((
146 input,
147 ChopFrame {
148 frame_type,
149 offset_delta,
150 },
151 ))
152}
153
154fn same_frame_extended_parser(
155 input: &[u8],
156 frame_type: u8,
157) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
158 let (input, offset_delta) = be_u16(input)?;
159 Ok((
160 input,
161 SameFrameExtended {
162 frame_type,
163 offset_delta,
164 },
165 ))
166}
167
168fn append_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
169 let (input, offset_delta) = be_u16(input)?;
170 let (input, locals) = count(verification_type_parser, (frame_type - 251) as usize)(input)?;
171 Ok((
172 input,
173 AppendFrame {
174 frame_type,
175 offset_delta,
176 locals,
177 },
178 ))
179}
180
181fn full_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
182 let (input, offset_delta) = be_u16(input)?;
183 let (input, number_of_locals) = be_u16(input)?;
184 let (input, locals) = count(verification_type_parser, number_of_locals as usize)(input)?;
185 let (input, number_of_stack_items) = be_u16(input)?;
186 let (input, stack) = count(verification_type_parser, number_of_stack_items as usize)(input)?;
187 Ok((
188 input,
189 FullFrame {
190 frame_type,
191 offset_delta,
192 number_of_locals,
193 locals,
194 number_of_stack_items,
195 stack,
196 },
197 ))
198}
199
200fn stack_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
201 match frame_type {
202 0..=63 => same_frame_parser(input, frame_type),
203 64..=127 => same_locals_1_stack_item_frame_parser(input, frame_type),
204 247 => same_locals_1_stack_item_frame_extended_parser(input, frame_type),
205 248..=250 => chop_frame_parser(input, frame_type),
206 251 => same_frame_extended_parser(input, frame_type),
207 252..=254 => append_frame_parser(input, frame_type),
208 255 => full_frame_parser(input, frame_type),
209 _ => Result::Err(Err::Error(error_position!(input, ErrorKind::NoneOf))),
210 }
211}
212
213fn stack_map_frame_entry_parser(input: &[u8]) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
214 let (input, frame_type) = be_u8(input)?;
215 let (input, stack_frame) = stack_frame_parser(input, frame_type)?;
216 Ok((input, stack_frame))
217}
218
219pub fn stack_map_table_attribute_parser(
220 input: &[u8],
221) -> Result<(&[u8], StackMapTableAttribute), Err<&[u8]>> {
222 let (input, number_of_entries) = be_u16(input)?;
223 let (input, entries) = count(stack_map_frame_entry_parser, number_of_entries as usize)(input)?;
224 Ok((
225 input,
226 StackMapTableAttribute {
227 number_of_entries,
228 entries,
229 },
230 ))
231}
232
233pub fn exceptions_attribute_parser(
234 input: &[u8],
235) -> Result<(&[u8], ExceptionsAttribute), Err<&[u8]>> {
236 let (input, exception_table_length) = be_u16(input)?;
237 let (input, exception_table) = count(be_u16, exception_table_length as usize)(input)?;
238 Ok((
239 input,
240 ExceptionsAttribute {
241 exception_table_length,
242 exception_table,
243 },
244 ))
245}
246
247pub fn constant_value_attribute_parser(
248 input: &[u8],
249) -> Result<(&[u8], ConstantValueAttribute), Err<&[u8]>> {
250 let (input, constant_value_index) = be_u16(input)?;
251 Ok((
252 input,
253 ConstantValueAttribute {
254 constant_value_index,
255 },
256 ))
257}
258
259fn bootstrap_method_parser(input: &[u8]) -> Result<(&[u8], BootstrapMethod), Err<&[u8]>> {
260 let (input, bootstrap_method_ref) = be_u16(input)?;
261 let (input, num_bootstrap_arguments) = be_u16(input)?;
262 let (input, bootstrap_arguments) = count(be_u16, num_bootstrap_arguments as usize)(input)?;
263 Ok((
264 input,
265 BootstrapMethod {
266 bootstrap_method_ref,
267 num_bootstrap_arguments,
268 bootstrap_arguments,
269 },
270 ))
271}
272
273pub fn bootstrap_methods_attribute_parser(
274 input: &[u8],
275) -> Result<(&[u8], BootstrapMethodsAttribute), Err<&[u8]>> {
276 let (input, num_bootstrap_methods) = be_u16(input)?;
277 let (input, bootstrap_methods) =
278 count(bootstrap_method_parser, num_bootstrap_methods as usize)(input)?;
279 Ok((
280 input,
281 BootstrapMethodsAttribute {
282 num_bootstrap_methods,
283 bootstrap_methods,
284 },
285 ))
286}
287
288pub fn sourcefile_attribute_parser(
289 input: &[u8],
290) -> Result<(&[u8], SourceFileAttribute), Err<&[u8]>> {
291 let (input, attribute_name_index) = be_u16(input)?;
292 let (input, attribute_length) = be_u32(input)?;
293 let (input, sourcefile_index) = be_u16(input)?;
294 Ok((
295 input,
296 SourceFileAttribute {
297 attribute_name_index,
298 attribute_length,
299 sourcefile_index,
300 },
301 ))
302}