1use super::{Ident, LitPosInt, LitUuid, TypeNameOrInline};
2use crate::error::{
3 DuplicateEventId, DuplicateFunctionId, DuplicateServiceItem, InvalidEventId, InvalidFunctionId,
4 InvalidServiceUuid, InvalidServiceVersion,
5};
6use crate::grammar::Rule;
7use crate::validate::Validate;
8use crate::warning::{NonCamelCaseService, NonSnakeCaseEvent, NonSnakeCaseFunction};
9use crate::Span;
10use pest::iterators::Pair;
11
12#[derive(Debug, Clone)]
13pub struct ServiceDef {
14 span: Span,
15 name: Ident,
16 uuid: LitUuid,
17 ver: LitPosInt,
18 items: Vec<ServiceItem>,
19 fn_fallback: Option<FunctionFallbackDef>,
20 ev_fallback: Option<EventFallbackDef>,
21}
22
23impl ServiceDef {
24 pub(crate) fn parse(pair: Pair<Rule>) -> Self {
25 assert_eq!(pair.as_rule(), Rule::service_def);
26
27 let span = Span::from_pair(&pair);
28
29 let mut pairs = pair.into_inner();
30 pairs.next().unwrap(); let pair = pairs.next().unwrap();
33 let name = Ident::parse(pair);
34
35 pairs.next().unwrap(); let pair = pairs.next().unwrap();
38 let uuid = Self::parse_uuid(pair);
39
40 let pair = pairs.next().unwrap();
41 let ver = Self::parse_version(pair);
42
43 let mut items = Vec::new();
44 let mut fn_fallback = None;
45 let mut ev_fallback = None;
46
47 for pair in pairs {
48 match pair.as_rule() {
49 Rule::service_item => items.push(ServiceItem::parse(pair)),
50
51 Rule::service_fallback => {
52 for pair in pair.into_inner() {
53 match pair.as_rule() {
54 Rule::fn_fallback => {
55 fn_fallback = Some(FunctionFallbackDef::parse(pair))
56 }
57
58 Rule::event_fallback => {
59 ev_fallback = Some(EventFallbackDef::parse(pair))
60 }
61
62 _ => unreachable!(),
63 }
64 }
65 }
66
67 Rule::tok_cur_close => break,
68 _ => unreachable!(),
69 }
70 }
71
72 Self {
73 span,
74 name,
75 uuid,
76 ver,
77 items,
78 fn_fallback,
79 ev_fallback,
80 }
81 }
82
83 fn parse_uuid(pair: Pair<Rule>) -> LitUuid {
84 assert_eq!(pair.as_rule(), Rule::service_uuid);
85 let mut pairs = pair.into_inner();
86 pairs.next().unwrap(); pairs.next().unwrap(); let pair = pairs.next().unwrap();
89 LitUuid::parse(pair)
90 }
91
92 fn parse_version(pair: Pair<Rule>) -> LitPosInt {
93 assert_eq!(pair.as_rule(), Rule::service_version);
94 let mut pairs = pair.into_inner();
95 pairs.next().unwrap(); pairs.next().unwrap(); let pair = pairs.next().unwrap();
98 LitPosInt::parse(pair)
99 }
100
101 pub(crate) fn validate(&self, validate: &mut Validate) {
102 InvalidServiceUuid::validate(self, validate);
103 InvalidServiceVersion::validate(self, validate);
104 DuplicateServiceItem::validate(self, validate);
105 DuplicateFunctionId::validate(self, validate);
106 DuplicateEventId::validate(self, validate);
107 NonCamelCaseService::validate(self, validate);
108
109 self.name.validate(validate);
110
111 for item in &self.items {
112 item.validate(validate);
113 }
114
115 if let Some(ref fn_fallback) = self.fn_fallback {
116 fn_fallback.validate(validate);
117 }
118
119 if let Some(ref ev_fallback) = self.ev_fallback {
120 ev_fallback.validate(validate);
121 }
122 }
123
124 pub fn span(&self) -> Span {
125 self.span
126 }
127
128 pub fn name(&self) -> &Ident {
129 &self.name
130 }
131
132 pub fn uuid(&self) -> &LitUuid {
133 &self.uuid
134 }
135
136 pub fn version(&self) -> &LitPosInt {
137 &self.ver
138 }
139
140 pub fn items(&self) -> &[ServiceItem] {
141 &self.items
142 }
143
144 pub fn function_fallback(&self) -> Option<&FunctionFallbackDef> {
145 self.fn_fallback.as_ref()
146 }
147
148 pub fn event_fallback(&self) -> Option<&EventFallbackDef> {
149 self.ev_fallback.as_ref()
150 }
151}
152
153#[derive(Debug, Clone)]
154pub enum ServiceItem {
155 Function(FunctionDef),
156 Event(EventDef),
157}
158
159impl ServiceItem {
160 fn parse(pair: Pair<Rule>) -> Self {
161 assert_eq!(pair.as_rule(), Rule::service_item);
162 let mut pairs = pair.into_inner();
163 let pair = pairs.next().unwrap();
164 match pair.as_rule() {
165 Rule::fn_def => Self::Function(FunctionDef::parse(pair)),
166 Rule::event_def => Self::Event(EventDef::parse(pair)),
167 _ => unreachable!(),
168 }
169 }
170
171 fn validate(&self, validate: &mut Validate) {
172 match self {
173 Self::Function(i) => i.validate(validate),
174 Self::Event(i) => i.validate(validate),
175 }
176 }
177
178 pub fn span(&self) -> Span {
179 match self {
180 Self::Function(i) => i.span(),
181 Self::Event(i) => i.span(),
182 }
183 }
184
185 pub fn name(&self) -> &Ident {
186 match self {
187 Self::Function(i) => i.name(),
188 Self::Event(i) => i.name(),
189 }
190 }
191}
192
193#[derive(Debug, Clone)]
194pub struct FunctionDef {
195 span: Span,
196 name: Ident,
197 id: LitPosInt,
198 args: Option<FunctionPart>,
199 ok: Option<FunctionPart>,
200 err: Option<FunctionPart>,
201}
202
203impl FunctionDef {
204 fn parse(pair: Pair<Rule>) -> Self {
205 assert_eq!(pair.as_rule(), Rule::fn_def);
206
207 let span = Span::from_pair(&pair);
208
209 let mut pairs = pair.into_inner();
210
211 pairs.next().unwrap(); let pair = pairs.next().unwrap();
214 let name = Ident::parse(pair);
215
216 pairs.next().unwrap(); let pair = pairs.next().unwrap();
219 let id = LitPosInt::parse(pair);
220
221 let mut args = None;
222 let mut ok = None;
223 let mut err = None;
224 for pair in pairs {
225 match pair.as_rule() {
226 Rule::fn_args => args = Some(FunctionPart::parse(pair)),
227 Rule::fn_ok => ok = Some(FunctionPart::parse(pair)),
228 Rule::fn_err => err = Some(FunctionPart::parse(pair)),
229 Rule::type_name_or_inline => ok = Some(FunctionPart::parse(pair)),
230
231 Rule::tok_cur_open | Rule::tok_cur_close | Rule::tok_eq | Rule::tok_term => {}
232 _ => unreachable!(),
233 }
234 }
235
236 Self {
237 span,
238 name,
239 id,
240 args,
241 ok,
242 err,
243 }
244 }
245
246 fn validate(&self, validate: &mut Validate) {
247 NonSnakeCaseFunction::validate(self, validate);
248 InvalidFunctionId::validate(self, validate);
249
250 self.name.validate(validate);
251
252 if let Some(ref args) = self.args {
253 args.validate(validate);
254 }
255
256 if let Some(ref ok) = self.ok {
257 ok.validate(validate);
258 }
259
260 if let Some(ref err) = self.err {
261 err.validate(validate);
262 }
263 }
264
265 pub fn span(&self) -> Span {
266 self.span
267 }
268
269 pub fn name(&self) -> &Ident {
270 &self.name
271 }
272
273 pub fn id(&self) -> &LitPosInt {
274 &self.id
275 }
276
277 pub fn args(&self) -> Option<&FunctionPart> {
278 self.args.as_ref()
279 }
280
281 pub fn ok(&self) -> Option<&FunctionPart> {
282 self.ok.as_ref()
283 }
284
285 pub fn err(&self) -> Option<&FunctionPart> {
286 self.err.as_ref()
287 }
288}
289
290#[derive(Debug, Clone)]
291pub struct FunctionPart {
292 span: Span,
293 part_type: TypeNameOrInline,
294}
295
296impl FunctionPart {
297 fn parse(pair: Pair<Rule>) -> Self {
298 let span = Span::from_pair(&pair);
299
300 let pair = if (pair.as_rule() == Rule::fn_args)
301 || (pair.as_rule() == Rule::fn_ok)
302 || (pair.as_rule() == Rule::fn_err)
303 {
304 let mut pairs = pair.into_inner();
305
306 pairs.next().unwrap(); pairs.next().unwrap(); pairs.next().unwrap()
310 } else if pair.as_rule() == Rule::type_name_or_inline {
311 pair
312 } else {
313 unreachable!()
314 };
315
316 let part_type = TypeNameOrInline::parse(pair);
317 Self { span, part_type }
318 }
319
320 fn validate(&self, validate: &mut Validate) {
321 self.part_type.validate(validate);
322 }
323
324 pub fn span(&self) -> Span {
325 self.span
326 }
327
328 pub fn part_type(&self) -> &TypeNameOrInline {
329 &self.part_type
330 }
331}
332
333#[derive(Debug, Clone)]
334pub struct EventDef {
335 span: Span,
336 name: Ident,
337 id: LitPosInt,
338 event_type: Option<TypeNameOrInline>,
339}
340
341impl EventDef {
342 fn parse(pair: Pair<Rule>) -> Self {
343 assert_eq!(pair.as_rule(), Rule::event_def);
344
345 let span = Span::from_pair(&pair);
346
347 let mut pairs = pair.into_inner();
348
349 pairs.next().unwrap(); let pair = pairs.next().unwrap();
352 let name = Ident::parse(pair);
353
354 pairs.next().unwrap(); let pair = pairs.next().unwrap();
357 let id = LitPosInt::parse(pair);
358
359 let pair = pairs.next().unwrap();
360 let event_type = match pair.as_rule() {
361 Rule::tok_eq => {
362 let pair = pairs.next().unwrap();
363 Some(TypeNameOrInline::parse(pair))
364 }
365 Rule::tok_term => None,
366 _ => unreachable!(),
367 };
368
369 Self {
370 span,
371 name,
372 id,
373 event_type,
374 }
375 }
376
377 fn validate(&self, validate: &mut Validate) {
378 NonSnakeCaseEvent::validate(self, validate);
379 InvalidEventId::validate(self, validate);
380
381 self.name.validate(validate);
382 if let Some(ref event_type) = self.event_type {
383 event_type.validate(validate);
384 }
385 }
386
387 pub fn span(&self) -> Span {
388 self.span
389 }
390
391 pub fn name(&self) -> &Ident {
392 &self.name
393 }
394
395 pub fn id(&self) -> &LitPosInt {
396 &self.id
397 }
398
399 pub fn event_type(&self) -> Option<&TypeNameOrInline> {
400 self.event_type.as_ref()
401 }
402}
403
404#[derive(Debug, Clone)]
405pub struct FunctionFallbackDef {
406 span: Span,
407 name: Ident,
408}
409
410impl FunctionFallbackDef {
411 fn parse(pair: Pair<Rule>) -> Self {
412 assert_eq!(pair.as_rule(), Rule::fn_fallback);
413
414 let span = Span::from_pair(&pair);
415
416 let mut pairs = pair.into_inner();
417
418 pairs.next().unwrap(); let pair = pairs.next().unwrap();
421 let name = Ident::parse(pair);
422
423 Self { span, name }
424 }
425
426 fn validate(&self, validate: &mut Validate) {
427 self.name.validate(validate);
428 }
429
430 pub fn span(&self) -> Span {
431 self.span
432 }
433
434 pub fn name(&self) -> &Ident {
435 &self.name
436 }
437}
438
439#[derive(Debug, Clone)]
440pub struct EventFallbackDef {
441 span: Span,
442 name: Ident,
443}
444
445impl EventFallbackDef {
446 fn parse(pair: Pair<Rule>) -> Self {
447 assert_eq!(pair.as_rule(), Rule::event_fallback);
448
449 let span = Span::from_pair(&pair);
450
451 let mut pairs = pair.into_inner();
452
453 pairs.next().unwrap(); let pair = pairs.next().unwrap();
456 let name = Ident::parse(pair);
457
458 Self { span, name }
459 }
460
461 fn validate(&self, validate: &mut Validate) {
462 self.name.validate(validate);
463 }
464
465 pub fn span(&self) -> Span {
466 self.span
467 }
468
469 pub fn name(&self) -> &Ident {
470 &self.name
471 }
472}