1use nom::{
2 bytes::complete::take,
3 combinator::map,
4 number::complete::{be_f32, be_f64, be_u16, be_u32, be_u64, be_u8},
5 IResult,
6};
7
8use crate::types::*;
9
10pub fn parse_constant_pool(input: &[u8], count: u16) -> IResult<&[u8], Vec<ConstantPoolEntry>> {
11 let mut entries = Vec::with_capacity(count as usize);
12 let mut remaining = input;
15 let mut i = 1u16;
16 while i < count {
17 let (rem, entry) = parse_constant_pool_entry(remaining)?;
18 let takes_two = entry.takes_two_slots();
19 entries.push(entry);
20 i += 1;
21 if takes_two {
22 i += 1;
24 }
25 remaining = rem;
26 }
27 Ok((remaining, entries))
28}
29
30fn parse_constant_pool_entry(input: &[u8]) -> IResult<&[u8], ConstantPoolEntry> {
31 let (input, tag) = be_u8(input)?;
32 match tag {
33 cp_tag::UTF8 => map(parse_utf8_info, ConstantPoolEntry::Utf8)(input),
34 cp_tag::INTEGER => map(parse_integer_info, ConstantPoolEntry::Integer)(input),
35 cp_tag::FLOAT => map(parse_float_info, ConstantPoolEntry::Float)(input),
36 cp_tag::LONG => map(parse_long_info, ConstantPoolEntry::Long)(input),
37 cp_tag::DOUBLE => map(parse_double_info, ConstantPoolEntry::Double)(input),
38 cp_tag::CLASS => map(parse_class_info, ConstantPoolEntry::Class)(input),
39 cp_tag::STRING => map(parse_string_info, ConstantPoolEntry::String)(input),
40 cp_tag::FIELDREF => map(parse_fieldref_info, ConstantPoolEntry::Fieldref)(input),
41 cp_tag::METHODREF => map(parse_methodref_info, ConstantPoolEntry::Methodref)(input),
42 cp_tag::INTERFACE_METHODREF => map(
43 parse_interface_methodref_info,
44 ConstantPoolEntry::InterfaceMethodref,
45 )(input),
46 cp_tag::NAME_AND_TYPE => {
47 map(parse_name_and_type_info, ConstantPoolEntry::NameAndType)(input)
48 }
49 cp_tag::METHOD_HANDLE => {
50 map(parse_method_handle_info, ConstantPoolEntry::MethodHandle)(input)
51 }
52 cp_tag::METHOD_TYPE => map(parse_method_type_info, ConstantPoolEntry::MethodType)(input),
53 cp_tag::DYNAMIC => map(parse_dynamic_info, ConstantPoolEntry::Dynamic)(input),
54 cp_tag::INVOKE_DYNAMIC => {
55 map(parse_invoke_dynamic_info, ConstantPoolEntry::InvokeDynamic)(input)
56 }
57 cp_tag::MODULE => map(parse_module_info, ConstantPoolEntry::Module)(input),
58 cp_tag::PACKAGE => map(parse_package_info, ConstantPoolEntry::Package)(input),
59 _ => Err(nom::Err::Error(nom::error::Error::new(
60 input,
61 nom::error::ErrorKind::Tag,
62 ))),
63 }
64}
65
66fn parse_utf8_info(input: &[u8]) -> IResult<&[u8], Utf8Info> {
67 let (input, length) = be_u16(input)?;
68 let (input, bytes) = take(length as usize)(input)?;
69 let value = cesu8::from_java_cesu8(bytes)
71 .map(|s| s.into_owned())
72 .unwrap_or_else(|_| String::from_utf8_lossy(bytes).into_owned());
73 Ok((input, Utf8Info { value }))
74}
75
76fn parse_integer_info(input: &[u8]) -> IResult<&[u8], IntegerInfo> {
77 let (input, value) = be_u32(input)?;
78 Ok((
79 input,
80 IntegerInfo {
81 value: value as i32,
82 },
83 ))
84}
85
86fn parse_float_info(input: &[u8]) -> IResult<&[u8], FloatInfo> {
87 let (input, value) = be_f32(input)?;
88 Ok((input, FloatInfo { value }))
89}
90
91fn parse_long_info(input: &[u8]) -> IResult<&[u8], LongInfo> {
92 let (input, value) = be_u64(input)?;
93 Ok((
94 input,
95 LongInfo {
96 value: value as i64,
97 },
98 ))
99}
100
101fn parse_double_info(input: &[u8]) -> IResult<&[u8], DoubleInfo> {
102 let (input, value) = be_f64(input)?;
103 Ok((input, DoubleInfo { value }))
104}
105
106fn parse_class_info(input: &[u8]) -> IResult<&[u8], ClassInfo> {
107 let (input, name_index) = be_u16(input)?;
108 Ok((input, ClassInfo { name_index }))
109}
110
111fn parse_string_info(input: &[u8]) -> IResult<&[u8], StringInfo> {
112 let (input, string_index) = be_u16(input)?;
113 Ok((input, StringInfo { string_index }))
114}
115
116fn parse_fieldref_info(input: &[u8]) -> IResult<&[u8], FieldrefInfo> {
117 let (input, class_index) = be_u16(input)?;
118 let (input, name_and_type_index) = be_u16(input)?;
119 Ok((
120 input,
121 FieldrefInfo {
122 class_index,
123 name_and_type_index,
124 },
125 ))
126}
127
128fn parse_methodref_info(input: &[u8]) -> IResult<&[u8], MethodrefInfo> {
129 let (input, class_index) = be_u16(input)?;
130 let (input, name_and_type_index) = be_u16(input)?;
131 Ok((
132 input,
133 MethodrefInfo {
134 class_index,
135 name_and_type_index,
136 },
137 ))
138}
139
140fn parse_interface_methodref_info(input: &[u8]) -> IResult<&[u8], InterfaceMethodrefInfo> {
141 let (input, class_index) = be_u16(input)?;
142 let (input, name_and_type_index) = be_u16(input)?;
143 Ok((
144 input,
145 InterfaceMethodrefInfo {
146 class_index,
147 name_and_type_index,
148 },
149 ))
150}
151
152fn parse_name_and_type_info(input: &[u8]) -> IResult<&[u8], NameAndTypeInfo> {
153 let (input, name_index) = be_u16(input)?;
154 let (input, descriptor_index) = be_u16(input)?;
155 Ok((
156 input,
157 NameAndTypeInfo {
158 name_index,
159 descriptor_index,
160 },
161 ))
162}
163
164fn parse_method_handle_info(input: &[u8]) -> IResult<&[u8], MethodHandleInfo> {
165 let (input, reference_kind) = be_u8(input)?;
166 let (input, reference_index) = be_u16(input)?;
167 Ok((
168 input,
169 MethodHandleInfo {
170 reference_kind,
171 reference_index,
172 },
173 ))
174}
175
176fn parse_method_type_info(input: &[u8]) -> IResult<&[u8], MethodTypeInfo> {
177 let (input, descriptor_index) = be_u16(input)?;
178 Ok((input, MethodTypeInfo { descriptor_index }))
179}
180
181fn parse_dynamic_info(input: &[u8]) -> IResult<&[u8], DynamicInfo> {
182 let (input, bootstrap_method_attr_index) = be_u16(input)?;
183 let (input, name_and_type_index) = be_u16(input)?;
184 Ok((
185 input,
186 DynamicInfo {
187 bootstrap_method_attr_index,
188 name_and_type_index,
189 },
190 ))
191}
192
193fn parse_invoke_dynamic_info(input: &[u8]) -> IResult<&[u8], InvokeDynamicInfo> {
194 let (input, bootstrap_method_attr_index) = be_u16(input)?;
195 let (input, name_and_type_index) = be_u16(input)?;
196 Ok((
197 input,
198 InvokeDynamicInfo {
199 bootstrap_method_attr_index,
200 name_and_type_index,
201 },
202 ))
203}
204
205fn parse_module_info(input: &[u8]) -> IResult<&[u8], ModuleInfo> {
206 let (input, name_index) = be_u16(input)?;
207 Ok((input, ModuleInfo { name_index }))
208}
209
210fn parse_package_info(input: &[u8]) -> IResult<&[u8], PackageInfo> {
211 let (input, name_index) = be_u16(input)?;
212 Ok((input, PackageInfo { name_index }))
213}
214
215pub fn get_utf8(pool: &[ConstantPoolEntry], index: u16) -> Option<&str> {
218 if index == 0 {
219 return None;
220 }
221 let mut slot = 1u16;
223 for entry in pool {
224 if slot == index {
225 if let ConstantPoolEntry::Utf8(utf8) = entry {
226 return Some(&utf8.value);
227 }
228 return None;
229 }
230 slot += 1;
231 if entry.takes_two_slots() {
232 slot += 1;
233 }
234 }
235 None
236}
237
238pub fn get_entry(pool: &[ConstantPoolEntry], index: u16) -> Option<&ConstantPoolEntry> {
240 if index == 0 {
241 return None;
242 }
243 let mut slot = 1u16;
244 for entry in pool {
245 if slot == index {
246 return Some(entry);
247 }
248 slot += 1;
249 if entry.takes_two_slots() {
250 slot += 1;
251 }
252 }
253 None
254}