thrift_parser/
definition.rs

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, tuple};
7use nom::IResult;
8
9use crate::basic::{Identifier, IdentifierRef, ListSeparator, Separator};
10use crate::constant::{parse_list_separator, ConstValue, ConstValueRef, IntConstant};
11use crate::field::{Field, FieldRef};
12use crate::functions::{Function, FunctionRef};
13use crate::types::{FieldType, FieldTypeRef};
14use crate::Parser;
15
16// Const           ::=  'const' FieldType Identifier '=' ConstValue ListSeparator?
17#[derive(Debug, Clone, PartialEq)]
18pub struct ConstRef<'a> {
19    pub name: IdentifierRef<'a>,
20    pub type_: FieldTypeRef<'a>,
21    pub value: ConstValueRef<'a>,
22}
23
24impl<'a> Parser<'a> for ConstRef<'a> {
25    fn parse(input: &'a str) -> IResult<&'a str, Self> {
26        map(
27            tuple((
28                tag("const"),
29                preceded(Separator::parse, FieldTypeRef::parse),
30                preceded(Separator::parse, IdentifierRef::parse),
31                preceded(opt(Separator::parse), cchar('=')),
32                preceded(opt(Separator::parse), ConstValueRef::parse),
33                opt(pair(opt(Separator::parse), ListSeparator::parse)),
34            )),
35            |(_, type_, name, _, value, _)| Self { name, type_, value },
36        )(input)
37    }
38}
39
40#[derive(Debug, Clone, PartialEq)]
41pub struct Const {
42    pub name: Identifier,
43    pub type_: FieldType,
44    pub value: ConstValue,
45}
46
47impl<'a> From<ConstRef<'a>> for Const {
48    fn from(r: ConstRef<'a>) -> Self {
49        Self {
50            name: r.name.into(),
51            type_: r.type_.into(),
52            value: r.value.into(),
53        }
54    }
55}
56
57impl<'a> Parser<'a> for Const {
58    fn parse(input: &'a str) -> IResult<&'a str, Self> {
59        ConstRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
60    }
61}
62
63// Typedef         ::=  'typedef' DefinitionType Identifier
64// DefinitionType  ::=  BaseType | ContainerType
65// BaseType        ::=  'bool' | 'byte' | 'i8' | 'i16' | 'i32' | 'i64' | 'double' | 'string' | 'binary'
66// ContainerType   ::=  MapType | SetType | ListType
67#[derive(Debug, Clone, PartialEq)]
68pub struct TypedefRef<'a> {
69    pub old: FieldTypeRef<'a>,
70    pub alias: IdentifierRef<'a>,
71}
72
73impl<'a> Parser<'a> for TypedefRef<'a> {
74    fn parse(input: &'a str) -> IResult<&'a str, Self> {
75        map(
76            tuple((
77                tag("typedef"),
78                preceded(
79                    Separator::parse,
80                    alt((
81                        FieldTypeRef::parse_base_type,
82                        FieldTypeRef::parse_container_type,
83                    )),
84                ),
85                preceded(Separator::parse, IdentifierRef::parse),
86            )),
87            |(_, old, alias)| Self { old, alias },
88        )(input)
89    }
90}
91
92#[derive(Debug, Clone, PartialEq)]
93pub struct Typedef {
94    pub old: FieldType,
95    pub alias: Identifier,
96}
97
98impl<'a> From<TypedefRef<'a>> for Typedef {
99    fn from(r: TypedefRef<'a>) -> Self {
100        Self {
101            old: r.old.into(),
102            alias: r.alias.into(),
103        }
104    }
105}
106
107impl<'a> Parser<'a> for Typedef {
108    fn parse(input: &'a str) -> IResult<&'a str, Self> {
109        TypedefRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
110    }
111}
112
113// Enum            ::=  'enum' Identifier '{' (Identifier ('=' IntConstant)? ListSeparator?)* '}'
114#[derive(Debug, Clone, PartialEq)]
115pub struct EnumRef<'a> {
116    pub name: IdentifierRef<'a>,
117    pub children: Vec<EnumValueRef<'a>>,
118}
119
120#[derive(Debug, Clone, PartialEq)]
121pub struct EnumValueRef<'a> {
122    pub name: IdentifierRef<'a>,
123    pub value: Option<IntConstant>,
124}
125
126impl<'a> Parser<'a> for EnumRef<'a> {
127    fn parse(input: &'a str) -> IResult<&'a str, Self> {
128        map(
129            tuple((
130                tag("enum"),
131                preceded(Separator::parse, IdentifierRef::parse),
132                tuple((opt(Separator::parse), cchar('{'), opt(Separator::parse))),
133                separated_list0(parse_list_separator, EnumValueRef::parse),
134                preceded(opt(Separator::parse), cchar('}')),
135            )),
136            |(_, name, _, children, _)| Self { name, children },
137        )(input)
138    }
139}
140
141impl<'a> Parser<'a> for EnumValueRef<'a> {
142    fn parse(input: &'a str) -> IResult<&'a str, Self> {
143        map(
144            tuple((
145                IdentifierRef::parse,
146                opt(map(
147                    tuple((
148                        opt(Separator::parse),
149                        cchar('='),
150                        opt(Separator::parse),
151                        IntConstant::parse,
152                    )),
153                    |(_, _, _, i)| (i),
154                )),
155            )),
156            |(name, value)| Self { name, value },
157        )(input)
158    }
159}
160
161#[derive(Debug, Clone, PartialEq)]
162pub struct Enum {
163    pub name: Identifier,
164    pub children: Vec<EnumValue>,
165}
166
167#[derive(Debug, Clone, PartialEq)]
168pub struct EnumValue {
169    pub name: Identifier,
170    pub value: Option<IntConstant>,
171}
172
173impl<'a> From<EnumRef<'a>> for Enum {
174    fn from(r: EnumRef<'a>) -> Self {
175        Self {
176            name: r.name.into(),
177            children: r.children.into_iter().map(Into::into).collect(),
178        }
179    }
180}
181
182impl<'a> From<EnumValueRef<'a>> for EnumValue {
183    fn from(r: EnumValueRef<'a>) -> Self {
184        Self {
185            name: r.name.into(),
186            value: r.value,
187        }
188    }
189}
190
191impl<'a> Parser<'a> for Enum {
192    fn parse(input: &'a str) -> IResult<&'a str, Self> {
193        EnumRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
194    }
195}
196
197impl<'a> Parser<'a> for EnumValue {
198    fn parse(input: &'a str) -> IResult<&'a str, Self> {
199        EnumValueRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
200    }
201}
202
203// Struct          ::=  'struct' Identifier '{' Field* '}'
204#[derive(Debug, Clone, PartialEq)]
205pub struct StructRef<'a> {
206    pub name: IdentifierRef<'a>,
207    pub fields: Vec<FieldRef<'a>>,
208}
209
210impl<'a> Parser<'a> for StructRef<'a> {
211    fn parse(input: &'a str) -> IResult<&'a str, Self> {
212        map(
213            tuple((
214                pair(tag("struct"), Separator::parse),
215                IdentifierRef::parse,
216                delimited(opt(Separator::parse), cchar('{'), opt(Separator::parse)),
217                separated_list0(Separator::parse, FieldRef::parse),
218                pair(opt(Separator::parse), cchar('}')),
219            )),
220            |(_, name, _, fields, _)| Self { name, fields },
221        )(input)
222    }
223}
224
225#[derive(Debug, Clone, PartialEq)]
226pub struct Struct {
227    pub name: Identifier,
228    pub fields: Vec<Field>,
229}
230
231impl<'a> From<StructRef<'a>> for Struct {
232    fn from(r: StructRef<'a>) -> Self {
233        Self {
234            name: r.name.into(),
235            fields: r.fields.into_iter().map(Into::into).collect(),
236        }
237    }
238}
239
240impl<'a> Parser<'a> for Struct {
241    fn parse(input: &'a str) -> IResult<&'a str, Self> {
242        StructRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
243    }
244}
245
246// Union          ::=  'union' Identifier '{' Field* '}'
247#[derive(Debug, Clone, PartialEq)]
248pub struct UnionRef<'a> {
249    pub name: IdentifierRef<'a>,
250    pub fields: Vec<FieldRef<'a>>,
251}
252
253impl<'a> Parser<'a> for UnionRef<'a> {
254    fn parse(input: &'a str) -> IResult<&'a str, Self> {
255        map(
256            tuple((
257                pair(tag("union"), Separator::parse),
258                IdentifierRef::parse,
259                delimited(opt(Separator::parse), cchar('{'), opt(Separator::parse)),
260                separated_list0(Separator::parse, FieldRef::parse),
261                pair(opt(Separator::parse), cchar('}')),
262            )),
263            |(_, name, _, fields, _)| Self { name, fields },
264        )(input)
265    }
266}
267
268#[derive(Debug, Clone, PartialEq)]
269pub struct Union {
270    pub name: Identifier,
271    pub fields: Vec<Field>,
272}
273
274impl<'a> From<UnionRef<'a>> for Union {
275    fn from(r: UnionRef<'a>) -> Self {
276        Self {
277            name: r.name.into(),
278            fields: r.fields.into_iter().map(Into::into).collect(),
279        }
280    }
281}
282
283impl<'a> Parser<'a> for Union {
284    fn parse(input: &'a str) -> IResult<&'a str, Self> {
285        UnionRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
286    }
287}
288
289// Exception       ::=  'exception' Identifier '{' Field* '}'
290#[derive(Debug, Clone, PartialEq)]
291pub struct ExceptionRef<'a> {
292    pub name: IdentifierRef<'a>,
293    pub fields: Vec<FieldRef<'a>>,
294}
295
296impl<'a> Parser<'a> for ExceptionRef<'a> {
297    fn parse(input: &'a str) -> IResult<&'a str, Self> {
298        map(
299            tuple((
300                pair(tag("exception"), Separator::parse),
301                IdentifierRef::parse,
302                delimited(opt(Separator::parse), cchar('{'), opt(Separator::parse)),
303                separated_list0(Separator::parse, FieldRef::parse),
304                pair(opt(Separator::parse), cchar('}')),
305            )),
306            |(_, name, _, fields, _)| Self { name, fields },
307        )(input)
308    }
309}
310
311#[derive(Debug, Clone, PartialEq)]
312pub struct Exception {
313    pub name: Identifier,
314    pub fields: Vec<Field>,
315}
316
317impl<'a> From<ExceptionRef<'a>> for Exception {
318    fn from(r: ExceptionRef<'a>) -> Self {
319        Self {
320            name: r.name.into(),
321            fields: r.fields.into_iter().map(Into::into).collect(),
322        }
323    }
324}
325
326impl<'a> Parser<'a> for Exception {
327    fn parse(input: &'a str) -> IResult<&'a str, Self> {
328        ExceptionRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
329    }
330}
331
332// Service         ::=  'service' Identifier ( 'extends' Identifier )? '{' Function* '}'
333#[derive(Debug, Clone, PartialEq)]
334pub struct ServiceRef<'a> {
335    pub name: IdentifierRef<'a>,
336    pub extension: Option<IdentifierRef<'a>>,
337    pub functions: Vec<FunctionRef<'a>>,
338}
339
340impl<'a> Parser<'a> for ServiceRef<'a> {
341    fn parse(input: &'a str) -> IResult<&'a str, Self> {
342        map(
343            tuple((
344                delimited(
345                    pair(tag("service"), Separator::parse),
346                    IdentifierRef::parse,
347                    opt(Separator::parse),
348                ),
349                opt(map(
350                    tuple((
351                        tag("extends"),
352                        Separator::parse,
353                        IdentifierRef::parse,
354                        opt(Separator::parse),
355                    )),
356                    |(_, _, ext, _)| ext,
357                )),
358                delimited(
359                    pair(cchar('{'), opt(Separator::parse)),
360                    separated_list0(Separator::parse, FunctionRef::parse),
361                    pair(opt(Separator::parse), cchar('}')),
362                ),
363            )),
364            |(name, extension, functions)| Self {
365                name,
366                extension,
367                functions,
368            },
369        )(input)
370    }
371}
372
373#[derive(Debug, Clone, PartialEq)]
374pub struct Service {
375    pub name: Identifier,
376    pub extension: Option<Identifier>,
377    pub functions: Vec<Function>,
378}
379
380impl<'a> From<ServiceRef<'a>> for Service {
381    fn from(r: ServiceRef<'a>) -> Self {
382        Self {
383            name: r.name.into(),
384            extension: r.extension.map(Into::into),
385            functions: r.functions.into_iter().map(Into::into).collect(),
386        }
387    }
388}
389
390impl<'a> Parser<'a> for Service {
391    fn parse(input: &'a str) -> IResult<&'a str, Self> {
392        ServiceRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
393    }
394}
395
396#[cfg(test)]
397mod test {
398    use crate::basic::LiteralRef;
399
400    use super::*;
401
402    #[test]
403    fn test_const() {
404        assert_eq!(
405            ConstRef::parse("const bool is_rust_easy = 'yes!';")
406                .unwrap()
407                .1,
408            ConstRef {
409                name: IdentifierRef::from("is_rust_easy"),
410                type_: FieldTypeRef::Bool,
411                value: ConstValueRef::Literal(LiteralRef::from("yes!"))
412            }
413        );
414    }
415
416    #[test]
417    fn test_typedef() {
418        assert_eq!(
419            TypedefRef::parse("typedef i32 MyI32").unwrap().1,
420            TypedefRef {
421                old: FieldTypeRef::I32,
422                alias: IdentifierRef::from("MyI32")
423            }
424        );
425    }
426
427    #[test]
428    fn test_enum() {
429        let expected = EnumRef {
430            name: IdentifierRef::from("PL"),
431            children: vec![
432                EnumValueRef {
433                    name: IdentifierRef::from("Rust"),
434                    value: None,
435                },
436                EnumValueRef {
437                    name: IdentifierRef::from("Go"),
438                    value: Some(IntConstant::from(2)),
439                },
440                EnumValueRef {
441                    name: IdentifierRef::from("Cpp"),
442                    value: Some(IntConstant::from(3)),
443                },
444            ],
445        };
446        assert_eq!(
447            EnumRef::parse("enum PL { Rust Go=2 , Cpp = 3 }").unwrap().1,
448            expected
449        );
450        assert_eq!(
451            EnumRef::parse("enum PL{Rust Go=2,Cpp=3}").unwrap().1,
452            expected
453        );
454    }
455
456    #[test]
457    fn test_struct() {
458        let expected = StructRef {
459            name: IdentifierRef::from("user"),
460            fields: vec![
461                FieldRef {
462                    id: Some(IntConstant::from(1)),
463                    required: Some(false),
464                    type_: FieldTypeRef::String,
465                    name: IdentifierRef::from("name"),
466                    default: None,
467                },
468                FieldRef {
469                    id: Some(IntConstant::from(2)),
470                    required: None,
471                    type_: FieldTypeRef::I32,
472                    name: IdentifierRef::from("age"),
473                    default: Some(ConstValueRef::Int(IntConstant::from(18))),
474                },
475            ],
476        };
477        assert_eq!(
478            StructRef::parse("struct user{1:optional string name; 2:i32 age=18}")
479                .unwrap()
480                .1,
481            expected
482        );
483        assert_eq!(
484            StructRef::parse("struct user { 1 : optional string name ; 2 : i32 age = 18 }")
485                .unwrap()
486                .1,
487            expected
488        );
489    }
490
491    #[test]
492    fn test_service() {
493        let function = FunctionRef {
494            oneway: false,
495            returns: Some(FieldTypeRef::String),
496            name: IdentifierRef::from("GetUser"),
497            parameters: vec![FieldRef {
498                id: None,
499                required: Some(true),
500                type_: FieldTypeRef::String,
501                name: IdentifierRef::from("name"),
502                default: None,
503            }],
504            exceptions: None,
505        };
506        let expected = ServiceRef {
507            name: IdentifierRef::from("DemoService"),
508            extension: Some(IdentifierRef::from("BaseService")),
509            functions: vec![function.clone(), function],
510        };
511        assert_eq!(
512            ServiceRef::parse(
513                "service DemoService extends BaseService { \
514         string GetUser(required string name),
515         string GetUser(required string name) }"
516            )
517            .unwrap()
518            .1,
519            expected
520        );
521    }
522}