1use nom::{named, terminated, is_not, char,
2 switch, take, value, map,
3 pair, fold_many_m_n, delimited, many0,
4 alt, combinator::complete};
5
6#[cfg(test)]
7mod tests {
8 use crate::{FieldType, SingleType, MethodType};
9
10 #[test]
11 fn fields() {
12 assert_eq!(FieldType::parse("[[[Lfoo bar net;"), Some(FieldType {
13 base: SingleType::Reference(String::from("foo bar net")), array_cnt: 3
14 }));
15 }
16 #[test]
17 fn methods() {
18 assert_eq!(MethodType::parse("([B[[LFoo;I)[LNetwork;"), Some(MethodType {
19 params: vec![FieldType {
20 base: SingleType::Byte,
21 array_cnt: 1
22 }, FieldType {
23 base: SingleType::Reference(String::from("Foo")),
24 array_cnt: 2
25 }, FieldType {
26 base: SingleType::Int,
27 array_cnt: 0
28 }],
29 ret: Some(FieldType {
30 base: SingleType::Reference(String::from("Network")),
31 array_cnt: 1
32 })
33 }));
34 assert_eq!(MethodType::parse("([B[[LFoo;I)V"), Some(MethodType {
35 params: vec![FieldType {
36 base: SingleType::Byte,
37 array_cnt: 1
38 }, FieldType {
39 base: SingleType::Reference(String::from("Foo")),
40 array_cnt: 2
41 }, FieldType {
42 base: SingleType::Int,
43 array_cnt: 0
44 }],
45 ret: None
46 }))
47 }
48}
49
50named!(semi_terminated<&str, &str>, terminated!(is_not!(";"), char!(';')));
51
52named!(single<&str, SingleType>, switch!(take!(1),
53 "B" => value!(SingleType::Byte) |
54 "C" => value!(SingleType::Char) |
55 "D" => value!(SingleType::Double) |
56 "F" => value!(SingleType::Float) |
57 "I" => value!(SingleType::Int) |
58 "J" => value!(SingleType::Long) |
59 "S" => value!(SingleType::Short) |
60 "Z" => value!(SingleType::Boolean) |
61 "L" => map!(semi_terminated, |v| SingleType::Reference(String::from(v))))
62);
63
64named!(field<&str, FieldType>, map!(
65 pair!(fold_many_m_n!(0, 255, char!('['), 0u8, |v, _| v + 1), single),
66 |v: (u8, SingleType)| FieldType {base: v.1, array_cnt: v.0}
67));
68
69named!(ret<&str, Option<FieldType>>, alt!(
70 map!(field, |v| Some(v)) |
71 map!(char!('V'), |_| None)
72));
73
74named!(method<&str, MethodType>, map!(pair!(
75 delimited!(char!('('), many0!(field), char!(')')),
76 ret),
77 |v| MethodType {params: v.0, ret: v.1}
78));
79
80named!(descriptor<&str, Descriptor>, alt!(
81 map!(method, |v| Descriptor::Method(v)) |
82 map!(field, |v| Descriptor::Field(v))
83));
84
85#[derive(Debug, Clone, Eq, PartialEq, Hash)]
87pub enum SingleType {
88 Byte,
89 Char,
90 Double,
91 Float,
92 Int,
93 Long,
94 Reference(String),
95 Short,
96 Boolean
97}
98
99impl SingleType {
100 pub fn parse(input: &str) -> Option<Self> {
101 complete(single)(input).ok().map(|v| v.1)
102 }
103}
104
105#[derive(Debug, Clone, Eq, PartialEq, Hash)]
107pub struct FieldType {
108 pub base: SingleType,
109 pub array_cnt: u8
110}
111
112impl FieldType {
113 pub fn parse(input: &str) -> Option<Self> {
114 complete(field)(input).ok().map(|v| v.1)
115 }
116}
117
118impl From<SingleType> for FieldType {
119 fn from(v: SingleType) -> Self {
120 Self {
121 base: v,
122 array_cnt: 0
123 }
124 }
125}
126
127#[derive(Debug, Clone, Eq, PartialEq, Hash)]
129pub struct MethodType {
130 pub params: Vec<FieldType>,
131 pub ret: Option<FieldType>
132}
133
134impl MethodType {
135 pub fn parse(input: &str) -> Option<Self> {
136 complete(method)(input).ok().map(|v| v.1)
137 }
138}
139
140#[derive(Debug, Clone, Eq, PartialEq, Hash)]
142pub enum Descriptor {
143 Field(FieldType),
144 Method(MethodType)
145}
146
147impl Descriptor {
148 pub fn parse(input: &str) -> Option<Self> {
149 complete(descriptor)(input).ok().map(|v| v.1)
150 }
151}
152
153impl From<FieldType> for Descriptor {
154 fn from(v: FieldType) -> Self {
156 Descriptor::Field(v)
157 }
158}
159
160impl From<MethodType> for Descriptor {
161 fn from(v: MethodType) -> Self {
163 Descriptor::Method(v)
164 }
165}