pclass_parser/class_parser/
signature.rs

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    /*
26    TestNG, org.testng.collections.Maps
27
28    <K:Ljava/lang/Object;V:Ljava/lang/Object;>(Ljava/util/Map<TK;TV;>;)Ljava/util/Map<TK;TV;>;
29
30    public static <K extends java.lang.Object, V extends java.lang.Object> java.util.Map<K, V> newHashMap(java.util.Map<K, V>);
31    */
32    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
128///////////////////////////
129//parser
130///////////////////////////
131
132fn 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    // should stop when reach ';' or '<'
152    //such as:
153    //(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
154    // if only take_till(|c| c == ';'), can't process like:
155    //    Lxx/xx/xx<Lxx/xx/xx;>;
156    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    //signature like:
172    //Ljava/lang/Class<+Lcom/google/inject/Module;>;
173    //<=> 'java.lang.Class<? extends com.google.inject.Module>'
174    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    //build results
186    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            // when successful, a nom parser returns a tuple of
243            // the remaining input and the output value.
244            // So we replace the captured input data with the
245            // remaining input, to be parsed on the next call
246            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    //'T' tag in args
467    #[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}