thrift_parser/
document.rs

1use nom::branch::alt;
2use nom::combinator::{map, opt};
3use nom::multi::many0;
4use nom::sequence::delimited;
5use nom::IResult;
6
7use crate::basic::Separator;
8use crate::definition::{
9    Const, ConstRef, Enum, EnumRef, Exception, ExceptionRef, Service, ServiceRef, Struct,
10    StructRef, Typedef, TypedefRef, Union, UnionRef,
11};
12use crate::header::{CppInclude, CppIncludeRef, Include, IncludeRef, Namespace, NamespaceRef};
13use crate::Parser;
14
15#[derive(PartialEq, Debug, Clone, Default)]
16pub struct DocumentRef<'a> {
17    pub includes: Vec<IncludeRef<'a>>,
18    pub cpp_includes: Vec<CppIncludeRef<'a>>,
19    pub namespaces: Vec<NamespaceRef<'a>>,
20    pub typedefs: Vec<TypedefRef<'a>>,
21    pub consts: Vec<ConstRef<'a>>,
22    pub enums: Vec<EnumRef<'a>>,
23    pub structs: Vec<StructRef<'a>>,
24    pub unions: Vec<UnionRef<'a>>,
25    pub exceptions: Vec<ExceptionRef<'a>>,
26    pub services: Vec<ServiceRef<'a>>,
27}
28
29impl<'a> Parser<'a> for DocumentRef<'a> {
30    fn parse(input: &'a str) -> IResult<&'a str, Self> {
31        let mut target = Self::default();
32        let includes = &mut target.includes;
33        let cpp_includes = &mut target.cpp_includes;
34        let namespaces = &mut target.namespaces;
35        let typedefs = &mut target.typedefs;
36        let consts = &mut target.consts;
37        let enums = &mut target.enums;
38        let structs = &mut target.structs;
39        let unions = &mut target.unions;
40        let exceptions = &mut target.exceptions;
41        let services = &mut target.services;
42
43        let (remains, _) = many0(delimited(
44            opt(Separator::parse),
45            alt((
46                map(IncludeRef::parse, |i| includes.push(i)),
47                map(CppIncludeRef::parse, |i| cpp_includes.push(i)),
48                map(NamespaceRef::parse, |i| namespaces.push(i)),
49                map(TypedefRef::parse, |i| typedefs.push(i)),
50                map(ConstRef::parse, |i| consts.push(i)),
51                map(EnumRef::parse, |i| enums.push(i)),
52                map(StructRef::parse, |i| structs.push(i)),
53                map(UnionRef::parse, |i| unions.push(i)),
54                map(ExceptionRef::parse, |i| exceptions.push(i)),
55                map(ServiceRef::parse, |i| services.push(i)),
56            )),
57            opt(Separator::parse),
58        ))(input)?;
59        Ok((remains, target))
60    }
61}
62
63#[derive(PartialEq, Debug, Clone, Default)]
64pub struct Document {
65    pub includes: Vec<Include>,
66    pub cpp_includes: Vec<CppInclude>,
67    pub namespaces: Vec<Namespace>,
68    pub typedefs: Vec<Typedef>,
69    pub consts: Vec<Const>,
70    pub enums: Vec<Enum>,
71    pub structs: Vec<Struct>,
72    pub unions: Vec<Union>,
73    pub exceptions: Vec<Exception>,
74    pub services: Vec<Service>,
75}
76
77impl<'a> From<DocumentRef<'a>> for Document {
78    fn from(r: DocumentRef<'a>) -> Self {
79        Self {
80            includes: r.includes.into_iter().map(Into::into).collect(),
81            cpp_includes: r.cpp_includes.into_iter().map(Into::into).collect(),
82            namespaces: r.namespaces.into_iter().map(Into::into).collect(),
83            typedefs: r.typedefs.into_iter().map(Into::into).collect(),
84            consts: r.consts.into_iter().map(Into::into).collect(),
85            enums: r.enums.into_iter().map(Into::into).collect(),
86            structs: r.structs.into_iter().map(Into::into).collect(),
87            unions: r.unions.into_iter().map(Into::into).collect(),
88            exceptions: r.exceptions.into_iter().map(Into::into).collect(),
89            services: r.services.into_iter().map(Into::into).collect(),
90        }
91    }
92}
93
94impl<'a> Parser<'a> for Document {
95    fn parse(input: &'a str) -> IResult<&'a str, Self> {
96        DocumentRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use crate::basic::LiteralRef;
103
104    use super::*;
105
106    #[test]
107    fn test_document() {
108        let expected = DocumentRef {
109            includes: vec![IncludeRef::from(LiteralRef::from("another.thrift"))],
110            ..Default::default()
111        };
112        assert_eq!(
113            DocumentRef::parse("include 'another.thrift'").unwrap().1,
114            expected
115        );
116    }
117}