thrift_parser/
header.rs

1use nom::branch::alt;
2use nom::bytes::complete::tag;
3use nom::combinator::map;
4use nom::sequence::{pair, preceded, tuple};
5use nom::IResult;
6
7use crate::basic::{Identifier, IdentifierRef, Literal, LiteralRef, Separator};
8use crate::Parser;
9
10// Include         ::=  'include' Literal
11#[derive(derive_newtype::NewType, Eq, PartialEq, Debug, Clone)]
12pub struct IncludeRef<'a>(LiteralRef<'a>);
13
14impl<'a> Parser<'a> for IncludeRef<'a> {
15    fn parse(input: &'a str) -> IResult<&'a str, Self> {
16        map(
17            preceded(pair(tag("include"), Separator::parse), LiteralRef::parse),
18            Self,
19        )(input)
20    }
21}
22
23#[derive(derive_newtype::NewType, Eq, PartialEq, Debug, Clone)]
24pub struct Include(Literal);
25
26impl<'a> From<IncludeRef<'a>> for Include {
27    fn from(r: IncludeRef<'a>) -> Self {
28        Self(r.0.into())
29    }
30}
31
32impl<'a> Parser<'a> for Include {
33    fn parse(input: &'a str) -> IResult<&'a str, Self> {
34        IncludeRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
35    }
36}
37
38// CppInclude      ::=  'cpp_include' Literal
39#[derive(derive_newtype::NewType, Eq, PartialEq, Debug, Clone)]
40pub struct CppIncludeRef<'a>(LiteralRef<'a>);
41
42impl<'a> Parser<'a> for CppIncludeRef<'a> {
43    fn parse(input: &'a str) -> IResult<&'a str, Self> {
44        map(
45            preceded(
46                pair(tag("cpp_include"), Separator::parse),
47                LiteralRef::parse,
48            ),
49            Self,
50        )(input)
51    }
52}
53
54#[derive(derive_newtype::NewType, Eq, PartialEq, Debug, Clone)]
55pub struct CppInclude(Literal);
56
57impl<'a> From<CppIncludeRef<'a>> for CppInclude {
58    fn from(r: CppIncludeRef<'a>) -> Self {
59        Self(r.0.into())
60    }
61}
62
63impl<'a> Parser<'a> for CppInclude {
64    fn parse(input: &'a str) -> IResult<&'a str, Self> {
65        CppIncludeRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
66    }
67}
68
69// Namespace       ::=  ( 'namespace' ( NamespaceScope Identifier ) )
70#[derive(Eq, PartialEq, Debug, Clone)]
71pub struct NamespaceRef<'a> {
72    pub scope: NamespaceScopeRef<'a>,
73    pub name: IdentifierRef<'a>,
74}
75
76// NamespaceScope  ::=  '*' | 'c_glib' | 'rust' | 'cpp' | 'delphi' | 'haxe' | 'go' | 'java' |
77// 'js' | 'lua' | 'netstd' | 'perl' | 'php' | 'py' | 'py.twisted' | 'rb' | 'st' | 'xsd'
78// We add rust into it.
79#[derive(derive_newtype::NewType, Eq, PartialEq, Debug, Clone)]
80pub struct NamespaceScopeRef<'a>(&'a str);
81
82impl<'a> Parser<'a> for NamespaceRef<'a> {
83    fn parse(input: &'a str) -> IResult<&'a str, Self> {
84        map(
85            tuple((
86                tag("namespace"),
87                preceded(Separator::parse, NamespaceScopeRef::parse),
88                preceded(Separator::parse, IdentifierRef::parse),
89            )),
90            |(_, scope, name)| Self { scope, name },
91        )(input)
92    }
93}
94
95impl<'a> Parser<'a> for NamespaceScopeRef<'a> {
96    fn parse(input: &'a str) -> IResult<&'a str, Self> {
97        map(
98            alt((
99                tag("*"),
100                tag("c_glib"),
101                tag("rust"),
102                tag("cpp"),
103                tag("delphi"),
104                tag("haxe"),
105                tag("go"),
106                tag("java"),
107                tag("js"),
108                tag("lua"),
109                tag("netstd"),
110                tag("perl"),
111                tag("php"),
112                tag("py"),
113                tag("py.twisted"),
114                tag("rb"),
115                tag("st"),
116                tag("xsd"),
117            )),
118            Self,
119        )(input)
120    }
121}
122
123#[derive(Eq, PartialEq, Debug, Clone)]
124pub struct Namespace {
125    pub scope: NamespaceScope,
126    pub name: Identifier,
127}
128
129#[derive(derive_newtype::NewType, Eq, PartialEq, Debug, Clone)]
130pub struct NamespaceScope(String);
131
132impl<'a> From<NamespaceRef<'a>> for Namespace {
133    fn from(r: NamespaceRef<'a>) -> Self {
134        Self {
135            scope: r.scope.into(),
136            name: r.name.into(),
137        }
138    }
139}
140
141impl<'a> From<NamespaceScopeRef<'a>> for NamespaceScope {
142    fn from(r: NamespaceScopeRef<'a>) -> Self {
143        Self(r.0.into())
144    }
145}
146
147impl<'a> Parser<'a> for Namespace {
148    fn parse(input: &'a str) -> IResult<&'a str, Self> {
149        NamespaceRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
150    }
151}
152
153impl<'a> Parser<'a> for NamespaceScope {
154    fn parse(input: &'a str) -> IResult<&'a str, Self> {
155        NamespaceScopeRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
156    }
157}
158
159#[cfg(test)]
160mod tests {
161    use super::*;
162
163    #[test]
164    fn test_include() {
165        assert_eq!(
166            IncludeRef::parse("include 'another.thrift'").unwrap().1,
167            IncludeRef::from(LiteralRef::from("another.thrift"))
168        )
169    }
170
171    #[test]
172    fn test_namespace() {
173        assert_eq!(
174            NamespaceRef::parse("namespace * MyNamespace").unwrap().1,
175            NamespaceRef {
176                scope: NamespaceScopeRef::from("*"),
177                name: IdentifierRef::from("MyNamespace")
178            }
179        )
180    }
181}