1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::character::complete::char as cchar;
use nom::combinator::{map, opt};
use nom::multi::separated_list0;
use nom::sequence::{delimited, pair, preceded, terminated, tuple};
use nom::IResult;
use crate::basic::{Identifier, ListSeparator, Separator};
use crate::field::Field;
use crate::types::FieldType;
use crate::Parser;
#[derive(Debug, Clone, PartialEq)]
pub struct Function<'a> {
pub oneway: bool,
pub returns: Option<FieldType<'a>>,
pub name: Identifier<'a>,
pub parameters: Vec<Field<'a>>,
pub exceptions: Option<Vec<Field<'a>>>,
}
impl<'a> Parser<'a> for Function<'a> {
fn parse(input: &'a str) -> IResult<&'a str, Self> {
map(
tuple((
map(opt(terminated(tag("oneway"), Separator::parse)), |x| {
x.is_some()
}),
terminated(
alt((
map(tag("void"), |_| None),
map(FieldType::parse, Some),
)),
Separator::parse,
),
terminated(Identifier::parse, opt(Separator::parse)),
terminated(
delimited(
cchar('('),
separated_list0(Separator::parse, Field::parse),
cchar(')'),
),
opt(Separator::parse),
),
opt(preceded(
pair(tag("throws"), Separator::parse),
delimited(
cchar('('),
separated_list0(Separator::parse, Field::parse),
cchar(')'),
),
)),
opt(pair(opt(Separator::parse), ListSeparator::parse)),
)),
|(oneway, returns, name, parameters, exceptions, _)| Self {
oneway,
returns,
name,
parameters,
exceptions,
},
)(input)
}
}
#[cfg(test)]
mod test {
use crate::basic::Literal;
use crate::constant::{ConstValue, IntConstant};
use super::*;
#[test]
fn test_function() {
let expected = Function {
oneway: false,
returns: Some(FieldType::String),
name: Identifier::from("GetUser"),
parameters: vec![Field {
id: None,
required: Some(true),
type_: FieldType::String,
name: Identifier::from("name"),
default: Some(ConstValue::Literal(Literal::from("ihciah"))),
}],
exceptions: None,
};
assert_eq!(
Function::parse("string GetUser(required string name='ihciah')")
.unwrap()
.1,
expected
);
let expected = Function {
oneway: true,
returns: None,
name: Identifier::from("DeleteUser"),
parameters: vec![Field {
id: Some(IntConstant::from(10086)),
required: Some(false),
type_: FieldType::I32,
name: Identifier::from("age"),
default: None,
}],
exceptions: None,
};
assert_eq!(
Function::parse("oneway void DeleteUser(10086:optional i32 age)")
.unwrap()
.1,
expected
);
}
}