classfile_parser/constant_info/
parser.rs1use nom::{
2 bytes::complete::take,
3 combinator::map,
4 error::{Error, ErrorKind},
5 number::complete::{be_f32, be_f64, be_i32, be_i64, be_u16, be_u8},
6 Err,
7};
8
9use constant_info::*;
10
11fn utf8_constant(input: &[u8]) -> Utf8Constant {
12 let utf8_string =
13 cesu8::from_java_cesu8(input).unwrap_or_else(|_| String::from_utf8_lossy(input));
14 Utf8Constant {
15 utf8_string: utf8_string.to_string(),
16 bytes: input.to_owned(),
17 }
18}
19
20fn const_utf8(input: &[u8]) -> ConstantInfoResult {
21 let (input, length) = be_u16(input)?;
22 let (input, constant) = map(take(length), utf8_constant)(input)?;
23 Ok((input, ConstantInfo::Utf8(constant)))
24}
25
26fn const_integer(input: &[u8]) -> ConstantInfoResult {
27 let (input, value) = be_i32(input)?;
28 Ok((input, ConstantInfo::Integer(IntegerConstant { value })))
29}
30
31fn const_float(input: &[u8]) -> ConstantInfoResult {
32 let (input, value) = be_f32(input)?;
33 Ok((input, ConstantInfo::Float(FloatConstant { value })))
34}
35
36fn const_long(input: &[u8]) -> ConstantInfoResult {
37 let (input, value) = be_i64(input)?;
38 Ok((input, ConstantInfo::Long(LongConstant { value })))
39}
40
41fn const_double(input: &[u8]) -> ConstantInfoResult {
42 let (input, value) = be_f64(input)?;
43 Ok((input, ConstantInfo::Double(DoubleConstant { value })))
44}
45
46fn const_class(input: &[u8]) -> ConstantInfoResult {
47 let (input, name_index) = be_u16(input)?;
48 Ok((input, ConstantInfo::Class(ClassConstant { name_index })))
49}
50
51fn const_string(input: &[u8]) -> ConstantInfoResult {
52 let (input, string_index) = be_u16(input)?;
53 Ok((input, ConstantInfo::String(StringConstant { string_index })))
54}
55
56fn const_field_ref(input: &[u8]) -> ConstantInfoResult {
57 let (input, class_index) = be_u16(input)?;
58 let (input, name_and_type_index) = be_u16(input)?;
59 Ok((
60 input,
61 ConstantInfo::FieldRef(FieldRefConstant {
62 class_index,
63 name_and_type_index,
64 }),
65 ))
66}
67
68fn const_method_ref(input: &[u8]) -> ConstantInfoResult {
69 let (input, class_index) = be_u16(input)?;
70 let (input, name_and_type_index) = be_u16(input)?;
71 Ok((
72 input,
73 ConstantInfo::MethodRef(MethodRefConstant {
74 class_index,
75 name_and_type_index,
76 }),
77 ))
78}
79
80fn const_interface_method_ref(input: &[u8]) -> ConstantInfoResult {
81 let (input, class_index) = be_u16(input)?;
82 let (input, name_and_type_index) = be_u16(input)?;
83 Ok((
84 input,
85 ConstantInfo::InterfaceMethodRef(InterfaceMethodRefConstant {
86 class_index,
87 name_and_type_index,
88 }),
89 ))
90}
91
92fn const_name_and_type(input: &[u8]) -> ConstantInfoResult {
93 let (input, name_index) = be_u16(input)?;
94 let (input, descriptor_index) = be_u16(input)?;
95 Ok((
96 input,
97 ConstantInfo::NameAndType(NameAndTypeConstant {
98 name_index,
99 descriptor_index,
100 }),
101 ))
102}
103
104fn const_method_handle(input: &[u8]) -> ConstantInfoResult {
105 let (input, reference_kind) = be_u8(input)?;
106 let (input, reference_index) = be_u16(input)?;
107 Ok((
108 input,
109 ConstantInfo::MethodHandle(MethodHandleConstant {
110 reference_kind,
111 reference_index,
112 }),
113 ))
114}
115
116fn const_method_type(input: &[u8]) -> ConstantInfoResult {
117 let (input, descriptor_index) = be_u16(input)?;
118 Ok((
119 input,
120 ConstantInfo::MethodType(MethodTypeConstant { descriptor_index }),
121 ))
122}
123
124fn const_invoke_dynamic(input: &[u8]) -> ConstantInfoResult {
125 let (input, bootstrap_method_attr_index) = be_u16(input)?;
126 let (input, name_and_type_index) = be_u16(input)?;
127 Ok((
128 input,
129 ConstantInfo::InvokeDynamic(InvokeDynamicConstant {
130 bootstrap_method_attr_index,
131 name_and_type_index,
132 }),
133 ))
134}
135
136type ConstantInfoResult<'a> = Result<(&'a [u8], ConstantInfo), Err<Error<&'a [u8]>>>;
137type ConstantInfoVecResult<'a> = Result<(&'a [u8], Vec<ConstantInfo>), Err<Error<&'a [u8]>>>;
138
139fn const_block_parser(input: &[u8], const_type: u8) -> ConstantInfoResult {
140 match const_type {
141 1 => const_utf8(input),
142 3 => const_integer(input),
143 4 => const_float(input),
144 5 => const_long(input),
145 6 => const_double(input),
146 7 => const_class(input),
147 8 => const_string(input),
148 9 => const_field_ref(input),
149 10 => const_method_ref(input),
150 11 => const_interface_method_ref(input),
151 12 => const_name_and_type(input),
152 15 => const_method_handle(input),
153 16 => const_method_type(input),
154 18 => const_invoke_dynamic(input),
155 _ => Result::Err(Err::Error(error_position!(input, ErrorKind::Alt))),
156 }
157}
158
159fn single_constant_parser(input: &[u8]) -> ConstantInfoResult {
160 let (input, const_type) = be_u8(input)?;
161 let (input, const_block) = const_block_parser(input, const_type)?;
162 Ok((input, const_block))
163}
164
165pub fn constant_parser(i: &[u8], const_pool_size: usize) -> ConstantInfoVecResult {
166 let mut index = 0;
167 let mut input = i;
168 let mut res = Vec::with_capacity(const_pool_size);
169 while index < const_pool_size {
170 match single_constant_parser(input) {
171 Ok((i, o)) => {
172 let uses_two_entries =
175 matches!(o, ConstantInfo::Long(..) | ConstantInfo::Double(..));
176
177 res.push(o);
178 if uses_two_entries {
179 res.push(ConstantInfo::Unusable);
180 index += 1;
181 }
182 input = i;
183 index += 1;
184 }
185 _ => return Result::Err(Err::Error(error_position!(input, ErrorKind::Alt))),
186 }
187 }
188 Ok((input, res))
189}