1use crate::classfile::BytesRef;
2use crate::classfile::SignatureType as Type;
3
4use nom::bytes::complete::{take, take_till};
5use nom::character::complete::{char, one_of};
6use nom::combinator::{peek, verify};
7use nom::error::make_error;
8use nom::lib::std::fmt::{Error, Formatter};
9use nom::{
10 branch::alt,
11 bytes::complete::{is_not, tag},
12 error::{ErrorKind, ParseError, VerboseError},
13 multi::many1,
14 sequence::delimited,
15 AsBytes, Err, IResult,
16};
17
18#[derive(Debug)]
19pub struct ClassSignature {
20 pub items: Vec<Type>,
21}
22
23#[derive(Debug, Clone)]
24pub struct MethodSignature {
25 pub generics: Vec<(BytesRef, Type)>,
33
34 pub args: Vec<Type>,
35 pub retype: Type,
36}
37
38pub struct FieldSignature {
39 pub field_type: Type,
40}
41
42impl ClassSignature {
43 pub fn new(raw: &[u8]) -> Self {
44 let s = unsafe { std::str::from_utf8_unchecked(raw) };
45 let (_, cs) = Self::parse(s).unwrap();
46 cs
47 }
48
49 fn parse(i: &str) -> IResult<&str, ClassSignature> {
50 let (i, items) = parse_types(i)?;
51 Ok((i, ClassSignature { items }))
52 }
53}
54
55impl MethodSignature {
56 pub fn new(raw: &[u8]) -> Self {
57 let s = unsafe { std::str::from_utf8_unchecked(raw) };
58 let (_, r) = Self::parse(s).unwrap();
59 r
60 }
61
62 fn parse(i: &str) -> IResult<&str, MethodSignature> {
63 fn arg0(i: &str) -> IResult<&str, MethodSignature> {
64 let (i, _) = tag("()")(i)?;
65 let (i, retype) = parse_type(i)?;
66 Ok((
67 i,
68 MethodSignature {
69 generics: vec![],
70 args: vec![],
71 retype,
72 },
73 ))
74 }
75
76 fn args(i: &str) -> IResult<&str, MethodSignature> {
77 let (i_return, i_args) = delimited(char('('), is_not(")"), char(')'))(i)?;
78 let (_, args) = parse_types(i_args)?;
79 let (i, retype) = parse_type(i_return)?;
80 Ok((
81 i,
82 MethodSignature {
83 generics: vec![],
84 args,
85 retype,
86 },
87 ))
88 }
89
90 fn generic(i: &str) -> IResult<&str, MethodSignature> {
91 let (i, _) = tag("<")(i)?;
92 let (i, generics) = many1(generic_declare)(i)?;
93 let (i, _) = tag(">")(i)?;
94 let (i, mut r) = MethodSignature::parse(i)?;
95
96 r.generics = generics;
97
98 Ok((i, r))
99 }
100
101 alt((arg0, args, generic))(i)
102 }
103}
104
105impl FieldSignature {
106 pub fn new(raw: &[u8]) -> Self {
107 let s = unsafe { std::str::from_utf8_unchecked(raw) };
108 let (_, r) = Self::parse(s).unwrap();
109 r
110 }
111
112 fn parse(mut i: &str) -> IResult<&str, FieldSignature> {
113 let (i, field_type) = parse_type(i)?;
114 Ok((i, FieldSignature { field_type }))
115 }
116}
117
118impl Default for MethodSignature {
119 fn default() -> Self {
120 Self {
121 generics: Vec::new(),
122 args: Vec::new(),
123 retype: Type::Void,
124 }
125 }
126}
127
128fn primitive<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {
133 let (i, t) = one_of("BCDFIJSZV")(i)?;
134 let t = match t {
135 'B' => Type::Byte,
136 'C' => Type::Char,
137 'D' => Type::Double,
138 'F' => Type::Float,
139 'I' => Type::Int,
140 'J' => Type::Long,
141 'S' => Type::Short,
142 'Z' => Type::Boolean,
143 'V' => Type::Void,
144 _ => unreachable!(),
145 };
146
147 Ok((i, t))
148}
149
150fn object_desc<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&str, BytesRef, E> {
151 let (_, _) = alt((tag("L"), tag("T")))(input)?;
157 let (i, desc) = take_till(|c| c == ';' || c == '<')(input)?;
158 let (i, _) = tag(";")(i)?;
159 let mut buf = Vec::with_capacity(1 + desc.len() + 1);
160 buf.extend_from_slice(desc.as_bytes());
161 buf.push(b';');
162 let desc = std::sync::Arc::new(buf);
163 Ok((i, desc))
164}
165
166fn object_generic<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {
167 let (i, tag_prefix) = alt((tag("L"), tag("T")))(i)?;
168 let (i, container) = take_till(|c| c == '<')(i)?;
169 let (mut i, _) = tag("<")(i)?;
170
171 let mut prefix = None;
175 if i.chars().nth(0) == Some('+') {
176 prefix = Some(b'+');
177 let (i2, _) = tag("+")(i)?;
178 i = i2;
179 }
180
181 let (i, generic_args) = many1(parse_type)(i)?;
182 let (i, _) = tag(">")(i)?;
183 let (i, _) = tag(";")(i)?;
184
185 let mut buf = Vec::with_capacity(1 + container.len() + 1);
187 buf.extend_from_slice(tag_prefix.as_bytes());
188 buf.extend_from_slice(container.as_bytes());
189 buf.push(b';');
190 let desc = std::sync::Arc::new(buf);
191 Ok((i, Type::Object(desc, Some(generic_args), prefix)))
192}
193
194fn object_normal<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {
195 let (i, _) = peek(alt((tag("L"), tag("T"))))(i)?;
196 let (i, desc) = object_desc(i)?;
197 Ok((i, Type::Object(desc, None, None)))
198}
199
200fn object<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {
201 alt((object_normal, object_generic))(i)
202}
203
204fn array<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {
205 let (i, _) = peek(tag("["))(i)?;
206 let (i, ary_tags) = take_till(|c| c != '[')(i)?;
207 let (mut i, t) = peek(take(1u8))(i)?;
208
209 let mut buf = vec![];
210 buf.extend_from_slice(ary_tags.as_bytes());
211 match t {
212 "L" | "T" => {
213 let (i2, desc) = object_desc(i)?;
214 i = i2;
215 buf.extend_from_slice(desc.as_slice());
216 }
217 v => {
218 let (i2, _) = take(1u8)(i)?;
219 i = i2;
220 buf.extend_from_slice(v.as_bytes())
221 }
222 }
223 let desc = std::sync::Arc::new(buf);
224 Ok((i, Type::Array(desc)))
225}
226
227fn generic_declare<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, (BytesRef, Type), E> {
228 let (i, generic_type) = take_till(|c| c == ':')(i)?;
229 let (i, _) = tag(":")(i)?;
230 let (i, t) = parse_type(i)?;
231 let generic_type = std::sync::Arc::new(Vec::from(generic_type));
232 Ok((i, (generic_type, t)))
233}
234
235fn parse_type<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&str, Type, E> {
236 alt((primitive, object, array))(i)
237}
238
239fn parse_types<'a, E: ParseError<&'a str>>(mut input: &'a str) -> IResult<&str, Vec<Type>, E> {
240 let it = std::iter::from_fn(move || {
241 match parse_type::<'a, E>(input) {
242 Ok((i, o)) => {
247 input = i;
248 Some(o)
249 }
250 _ => None,
251 }
252 });
253
254 let mut args = vec![];
255 for v in it {
256 args.push(v);
257 }
258
259 Ok((input, args))
260}
261
262#[cfg(test)]
263mod tests {
264 use super::ClassSignature;
265 use super::FieldSignature;
266 use super::MethodSignature;
267 use super::Type as SignatureType;
268 use std::sync::Arc;
269
270 #[test]
271 fn t_method_no_arg() {
272 let expected = MethodSignature {
273 generics: vec![],
274 args: vec![],
275 retype: SignatureType::Void,
276 };
277 let (_, r) = MethodSignature::parse("()V").unwrap();
278 assert_eq!(r.args, expected.args);
279 assert_eq!(r.retype, expected.retype);
280 }
281
282 #[test]
283 fn method_primitive() {
284 let table = vec![
285 (
286 MethodSignature {
287 generics: vec![],
288 args: vec![SignatureType::Byte],
289 retype: SignatureType::Void,
290 },
291 "(B)V",
292 ),
293 (
294 MethodSignature {
295 generics: vec![],
296 args: vec![SignatureType::Char],
297 retype: SignatureType::Void,
298 },
299 "(C)V",
300 ),
301 (
302 MethodSignature {
303 generics: vec![],
304 args: vec![SignatureType::Double],
305 retype: SignatureType::Void,
306 },
307 "(D)V",
308 ),
309 (
310 MethodSignature {
311 generics: vec![],
312 args: vec![SignatureType::Float],
313 retype: SignatureType::Void,
314 },
315 "(F)V",
316 ),
317 (
318 MethodSignature {
319 generics: vec![],
320 args: vec![SignatureType::Int],
321 retype: SignatureType::Void,
322 },
323 "(I)V",
324 ),
325 (
326 MethodSignature {
327 generics: vec![],
328 args: vec![SignatureType::Long],
329 retype: SignatureType::Void,
330 },
331 "(J)V",
332 ),
333 (
334 MethodSignature {
335 generics: vec![],
336 args: vec![SignatureType::Short],
337 retype: SignatureType::Void,
338 },
339 "(S)V",
340 ),
341 (
342 MethodSignature {
343 generics: vec![],
344 args: vec![SignatureType::Boolean],
345 retype: SignatureType::Void,
346 },
347 "(Z)V",
348 ),
349 ];
350
351 for (expected, desc) in table.iter() {
352 let (_, r) = MethodSignature::parse(desc).unwrap();
353 assert_eq!(r.args, expected.args);
354 assert_eq!(r.retype, expected.retype);
355 }
356 }
357
358 #[test]
359 fn method_array_object() {
360 let expected = MethodSignature {
361 generics: vec![],
362 args: vec![SignatureType::Array(Arc::new(Vec::from(
363 "[[Ljava/lang/String;",
364 )))],
365 retype: SignatureType::Void,
366 };
367 let (_, r) = MethodSignature::parse("([[Ljava/lang/String;)V").unwrap();
368 assert_eq!(r.args, expected.args);
369 assert_eq!(r.retype, expected.retype);
370 }
371
372 #[test]
373 fn method_mix() {
374 let expected = MethodSignature {
375 generics: vec![],
376 args: vec![
377 SignatureType::Byte,
378 SignatureType::Char,
379 SignatureType::Double,
380 SignatureType::Float,
381 SignatureType::Int,
382 SignatureType::Long,
383 SignatureType::Short,
384 SignatureType::Boolean,
385 SignatureType::Object(Arc::new(Vec::from("Ljava/lang/Integer;")), None, None),
386 ],
387 retype: SignatureType::Object(Arc::new(Vec::from("Ljava/lang/String;")), None, None),
388 };
389 let (_, r) =
390 MethodSignature::parse("(BCDFIJSZLjava/lang/Integer;)Ljava/lang/String;").unwrap();
391 assert_eq!(r.args, expected.args);
392 assert_eq!(r.retype, expected.retype);
393 }
394
395 #[test]
396 fn method_arg_generic() {
397 let generic_args = vec![SignatureType::Object(
398 Arc::new(Vec::from("Ljava/lang/String;")),
399 None,
400 None,
401 )];
402 let expected = MethodSignature {
403 generics: vec![],
404 args: vec![SignatureType::Object(
405 Arc::new(Vec::from("Ljava/util/List;")),
406 Some(generic_args),
407 None,
408 )],
409 retype: SignatureType::Void,
410 };
411 let (_, r) = MethodSignature::parse("(Ljava/util/List<Ljava/lang/String;>;)V").unwrap();
412 assert_eq!(r.args, expected.args);
413 assert_eq!(r.retype, expected.retype);
414
415 let expected = MethodSignature {
416 generics: vec![],
417 args: vec![
418 SignatureType::Object(
419 Arc::new(Vec::from("Lorg/testng/internal/IConfiguration;")),
420 None,
421 None,
422 ),
423 SignatureType::Object(Arc::new(Vec::from("Lorg/testng/ISuite;")), None, None),
424 SignatureType::Object(Arc::new(Vec::from("Lorg/testng/xml/XmlTest;")), None, None),
425 SignatureType::Object(Arc::new(Vec::from("Ljava/lang/String;")), None, None),
426 SignatureType::Object(
427 Arc::new(Vec::from(
428 "Lorg/testng/internal/annotations/IAnnotationFinder;",
429 )),
430 None,
431 None,
432 ),
433 SignatureType::Boolean,
434 SignatureType::Object(
435 Arc::new(Vec::from("Ljava/util/List;")),
436 Some(vec![SignatureType::Object(
437 Arc::new(Vec::from("Lorg/testng/IInvokedMethodListener;")),
438 None,
439 None,
440 )]),
441 None,
442 ),
443 ],
444 retype: SignatureType::Void,
445 };
446 let (_, r) = MethodSignature::parse("(Lorg/testng/internal/IConfiguration;Lorg/testng/ISuite;Lorg/testng/xml/XmlTest;Ljava/lang/String;Lorg/testng/internal/annotations/IAnnotationFinder;ZLjava/util/List<Lorg/testng/IInvokedMethodListener;>;)V").unwrap();
447 assert_eq!(r.args, expected.args);
448 assert_eq!(r.retype, expected.retype);
449 }
450
451 #[test]
452 fn generic1() {
453 let expected = MethodSignature {
454 generics: vec![],
455 args: vec![
456 SignatureType::Object(Arc::new(Vec::from("TK;")), None, None),
457 SignatureType::Object(Arc::new(Vec::from("TV;")), None, None),
458 ],
459 retype: SignatureType::Void,
460 };
461 let (_, r) = MethodSignature::parse("(TK;TV;)V").unwrap();
462 assert_eq!(r.args, expected.args);
463 assert_eq!(r.retype, expected.retype);
464 }
465
466 #[test]
468 fn generic2() {
469 let expected = MethodSignature {
470 generics: vec![],
471 args: vec![SignatureType::Object(
472 Arc::new(Vec::from("TK;")),
473 None,
474 None,
475 )],
476 retype: SignatureType::Object(
477 Arc::new(Vec::from("Ljava/util/Set;")),
478 Some(vec![SignatureType::Object(
479 Arc::new(Vec::from("TV;")),
480 None,
481 None,
482 )]),
483 None,
484 ),
485 };
486 let (_, r) = MethodSignature::parse("(TK;)Ljava/util/Set<TV;>;").unwrap();
487 assert_eq!(r.args, expected.args);
488 assert_eq!(r.retype, expected.retype);
489 }
490
491 #[test]
492 fn generic_nest1() {
493 let expected = MethodSignature {
494 generics: vec![],
495 args: vec![],
496 retype: SignatureType::Object(
497 Arc::new(Vec::from("Ljava/util/Set;")),
498 Some(vec![SignatureType::Object(
499 Arc::new(Vec::from("Ljava/util/Map$Entry;")),
500 Some(vec![
501 SignatureType::Object(Arc::new(Vec::from("TK;")), None, None),
502 SignatureType::Object(
503 Arc::new(Vec::from("Ljava/util/Set;")),
504 Some(vec![SignatureType::Object(
505 Arc::new(Vec::from("TV;")),
506 None,
507 None,
508 )]),
509 None,
510 ),
511 ]),
512 None,
513 )]),
514 None,
515 ),
516 };
517 let (_, r) = MethodSignature::parse(
518 "()Ljava/util/Set<Ljava/util/Map$Entry<TK;Ljava/util/Set<TV;>;>;>;",
519 )
520 .unwrap();
521 assert_eq!(r.args, expected.args);
522 assert_eq!(r.retype, expected.retype);
523 }
524
525 #[test]
526 fn generic_method() {
527 let expected = MethodSignature {
528 generics: vec![
529 (
530 Arc::new(Vec::from("K")),
531 SignatureType::Object(Arc::new(Vec::from("Ljava/lang/Object;")), None, None),
532 ),
533 (
534 Arc::new(Vec::from("V")),
535 SignatureType::Object(Arc::new(Vec::from("Ljava/lang/Object;")), None, None),
536 ),
537 ],
538 args: vec![SignatureType::Object(
539 Arc::new(Vec::from("Ljava/util/Map;")),
540 Some(vec![
541 SignatureType::Object(Arc::new(Vec::from("TK;")), None, None),
542 SignatureType::Object(Arc::new(Vec::from("TV;")), None, None),
543 ]),
544 None,
545 )],
546 retype: SignatureType::Object(
547 Arc::new(Vec::from("Ljava/util/Map;")),
548 Some(vec![
549 SignatureType::Object(Arc::new(Vec::from("TK;")), None, None),
550 SignatureType::Object(Arc::new(Vec::from("TV;")), None, None),
551 ]),
552 None,
553 ),
554 };
555 let (_, r) = MethodSignature::parse("<K:Ljava/lang/Object;V:Ljava/lang/Object;>(Ljava/util/Map<TK;TV;>;)Ljava/util/Map<TK;TV;>;").unwrap();
556 assert_eq!(r.args, expected.args);
557 assert_eq!(r.retype, expected.retype);
558 }
559
560 #[test]
561 fn method_return_generic() {
562 let generic_args = vec![SignatureType::Object(
563 Arc::new(Vec::from("Lorg/testng/ITestNGListener;")),
564 None,
565 None,
566 )];
567 let expected = MethodSignature {
568 generics: vec![],
569 args: vec![],
570 retype: SignatureType::Object(
571 Arc::new(Vec::from("Ljava/util/List;")),
572 Some(generic_args),
573 None,
574 ),
575 };
576 let (_, r) =
577 MethodSignature::parse("()Ljava/util/List<Lorg/testng/ITestNGListener;>;").unwrap();
578 assert_eq!(r.args, expected.args);
579 assert_eq!(r.retype, expected.retype);
580 }
581
582 #[test]
583 fn field() {
584 macro_rules! setup_test {
585 ($desc: expr, $tp: expr) => {
586 let (_, sig) = FieldSignature::parse($desc).unwrap();
587 assert_eq!(sig.field_type, $tp);
588 };
589 }
590
591 setup_test!("B", SignatureType::Byte);
592 setup_test!("C", SignatureType::Char);
593 setup_test!("D", SignatureType::Double);
594 setup_test!("F", SignatureType::Float);
595 setup_test!("I", SignatureType::Int);
596 setup_test!("J", SignatureType::Long);
597
598 let v = Vec::from("Ljava/lang/Object;");
599 let v = Arc::new(v);
600 setup_test!("Ljava/lang/Object;", SignatureType::Object(v, None, None));
601 setup_test!("S", SignatureType::Short);
602 setup_test!("Z", SignatureType::Boolean);
603
604 let v = Vec::from("[Ljava/lang/Object;");
605 let v = Arc::new(v);
606 setup_test!("[Ljava/lang/Object;", SignatureType::Array(v));
607
608 let v = Vec::from("[[[D");
609 let v = Arc::new(v);
610 setup_test!("[[[D", SignatureType::Array(v));
611 }
612
613 #[test]
614 fn t_class_signature() {
615 let (_, cs) = ClassSignature::parse("Ljava/lang/Object;Lorg/testng/ITestContext;Lorg/testng/internal/ITestResultNotifier;Lorg/testng/internal/thread/graph/IThreadWorkerFactory<Lorg/testng/ITestNGMethod;>;").unwrap();
616 let expected = ClassSignature {
617 items: vec![
618 SignatureType::Object(Arc::new(Vec::from("Ljava/lang/Object;")), None, None),
619 SignatureType::Object(Arc::new(Vec::from("Lorg/testng/ITestContext;")), None, None),
620 SignatureType::Object(
621 Arc::new(Vec::from("Lorg/testng/internal/ITestResultNotifier;")),
622 None,
623 None,
624 ),
625 SignatureType::Object(
626 Arc::new(Vec::from(
627 "Lorg/testng/internal/thread/graph/IThreadWorkerFactory;",
628 )),
629 Some(vec![SignatureType::Object(
630 Arc::new(Vec::from("Lorg/testng/ITestNGMethod;")),
631 None,
632 None,
633 )]),
634 None,
635 ),
636 ],
637 };
638 assert_eq!(cs.items, expected.items);
639 }
640}