1use nom::{
2 bytes::complete::tag,
3 character::complete::char,
4 combinator::map,
5 sequence::{preceded, tuple},
6 IResult,
7};
8
9use crate::idl::common::{parse_identifier, ws, Span};
10use crate::idl::r#type::{parse_opt_type, Type};
11
12#[cfg(test)]
13use crate::idl::common::assert_parse;
14
15#[derive(Debug, PartialEq)]
16pub struct Method {
17 pub name: String,
18 pub input: Option<Type>,
19 pub output: Option<Type>,
20}
21
22pub fn parse_method(input: Span) -> IResult<Span, Method> {
23 map(
24 tuple((
25 parse_identifier,
26 preceded(ws, preceded(char(':'), preceded(ws, parse_opt_type))),
27 preceded(ws, preceded(tag("->"), preceded(ws, parse_opt_type))),
28 )),
29 |(name, input, output)| Method {
30 name,
31 input,
32 output,
33 },
34 )(input)
35}
36
37#[test]
38fn test_parse_method_0() {
39 let contents = [
40 "ping: None -> None",
42 "ping:None->None",
44 "ping :None->None",
45 "ping: None->None",
46 "ping:None ->None",
47 "ping:None-> None",
48 ];
49 for content in contents.iter() {
50 assert_parse(
51 parse_method(Span::new(content)),
52 Method {
53 name: "ping".to_string(),
54 input: None,
55 output: None,
56 },
57 )
58 }
59}
60
61#[test]
62fn test_parse_method_1() {
63 use crate::idl::r#type::TypeRef;
64 let contents = [
65 "notify: Notification -> None",
67 "notify:Notification->None",
69 "notify :Notification->None",
70 "notify: Notification->None",
71 "notify:Notification ->None",
72 "notify:Notification-> None",
73 ];
74 for content in contents.iter() {
75 assert_parse(
76 parse_method(Span::new(content)),
77 Method {
78 name: "notify".to_string(),
79 input: Some(Type::Ref(TypeRef {
80 abs: false,
81 ns: vec![],
82 name: "Notification".to_string(),
83 generics: vec![],
84 })),
85 output: None,
86 },
87 )
88 }
89}
90
91#[test]
92fn test_parse_method_2() {
93 use crate::idl::r#type::TypeRef;
94 let contents = [
95 "get_time: None -> Time",
97 "get_time:None->Time",
99 "get_time :None->Time",
100 "get_time: None->Time",
101 "get_time:None ->Time",
102 "get_time:None-> Time",
103 ];
104 for content in contents.iter() {
105 assert_parse(
106 parse_method(Span::new(content)),
107 Method {
108 name: "get_time".to_string(),
109 input: None,
110 output: Some(Type::Ref(TypeRef {
111 abs: false,
112 ns: vec![],
113 name: "Time".to_string(),
114 generics: vec![],
115 })),
116 },
117 )
118 }
119}
120
121#[test]
122fn test_parse_method_3() {
123 use crate::idl::r#type::TypeRef;
124 let contents = [
125 "no_response: None -> Result<None, SomeError>",
127 "no_response:None->Result<None,SomeError>",
129 "no_response :None->Result<None,SomeError>",
130 "no_response: None->Result<None,SomeError>",
131 "no_response:None ->Result<None,SomeError>",
132 "no_response:None-> Result<None,SomeError>",
133 "no_response:None->Result <None,SomeError>",
134 "no_response:None->Result< None,SomeError>",
135 "no_response:None->Result<None ,SomeError>",
136 "no_response:None->Result<None, SomeError>",
137 "no_response:None->Result<None,SomeError >",
138 ];
139 for content in contents.iter() {
140 assert_parse(
141 parse_method(Span::new(content)),
142 Method {
143 name: "no_response".to_string(),
144 input: None,
145 output: Some(Type::Ref(TypeRef {
146 abs: false,
147 ns: vec![],
148 name: "Result".to_string(),
149 generics: vec![
150 Type::Ref(TypeRef {
151 abs: false,
152 ns: vec![],
153 name: "None".to_string(),
154 generics: vec![],
155 }),
156 Type::Ref(TypeRef {
157 abs: false,
158 ns: vec![],
159 name: "SomeError".to_string(),
160 generics: vec![],
161 }),
162 ],
163 })),
164 },
165 )
166 }
167}
168
169#[test]
170fn test_parse_method_4() {
171 use crate::idl::r#type::TypeRef;
172 let contents = [
173 "hello: HelloRequest -> Result<HelloResponse, HelloError>",
175 "hello:HelloRequest->Result<HelloResponse,HelloError>",
177 "hello :HelloRequest->Result<HelloResponse,HelloError>",
178 "hello: HelloRequest->Result<HelloResponse,HelloError>",
179 "hello:HelloRequest ->Result<HelloResponse,HelloError>",
180 "hello:HelloRequest-> Result<HelloResponse,HelloError>",
181 "hello:HelloRequest->Result <HelloResponse,HelloError>",
182 "hello:HelloRequest->Result< HelloResponse,HelloError>",
183 "hello:HelloRequest->Result<HelloResponse ,HelloError>",
184 "hello:HelloRequest->Result<HelloResponse, HelloError>",
185 "hello:HelloRequest->Result<HelloResponse,HelloError >",
186 ];
187 for content in contents.iter() {
188 assert_parse(
189 parse_method(Span::new(content)),
190 Method {
191 name: "hello".to_string(),
192 input: Some(Type::Ref(TypeRef {
193 abs: false,
194 ns: vec![],
195 name: "HelloRequest".to_string(),
196 generics: vec![],
197 })),
198 output: Some(Type::Ref(TypeRef {
199 abs: false,
200 ns: vec![],
201 name: "Result".to_string(),
202 generics: vec![
203 Type::Ref(TypeRef {
204 abs: false,
205 ns: vec![],
206 name: "HelloResponse".to_string(),
207 generics: vec![],
208 }),
209 Type::Ref(TypeRef {
210 abs: false,
211 ns: vec![],
212 name: "HelloError".to_string(),
213 generics: vec![],
214 }),
215 ],
216 })),
217 },
218 )
219 }
220}