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