1use nom::branch::alt;
2use nom::bytes::complete::tag;
3use nom::character::complete::char as cchar;
4use nom::combinator::{map, opt};
5use nom::sequence::{delimited, pair, preceded, separated_pair, terminated, tuple};
6use nom::IResult;
7
8use crate::basic::{Identifier, IdentifierRef, Literal, LiteralRef, Separator};
9use crate::Parser;
10
11#[derive(Debug, Clone, PartialEq)]
20pub enum FieldTypeRef<'a> {
21 Identifier(IdentifierRef<'a>),
22 Bool,
23 Byte,
24 I8,
25 I16,
26 I32,
27 I64,
28 Double,
29 String,
30 Binary,
31 Map(Box<FieldTypeRef<'a>>, Box<FieldTypeRef<'a>>),
32 Set(Box<FieldTypeRef<'a>>),
33 List(Box<FieldTypeRef<'a>>),
34}
35
36impl<'a> FieldTypeRef<'a> {
37 pub fn parse_base_type(input: &'a str) -> IResult<&'a str, Self> {
38 alt((
39 map(tag("bool"), |_| Self::Bool),
40 map(tag("byte"), |_| Self::Byte),
41 map(tag("i8"), |_| Self::I8),
42 map(tag("i16"), |_| Self::I16),
43 map(tag("i32"), |_| Self::I32),
44 map(tag("i64"), |_| Self::I64),
45 map(tag("double"), |_| Self::Double),
46 map(tag("string"), |_| Self::String),
47 map(tag("binary"), |_| Self::Binary),
48 ))(input)
49 }
50
51 pub fn parse_container_type(input: &'a str) -> IResult<&'a str, Self> {
52 alt((
53 map(
54 preceded(
55 tuple((
56 tag("map"),
57 opt(Separator::parse),
58 opt(terminated(CppTypeRef::parse, opt(Separator::parse))),
59 )),
60 delimited(
61 pair(cchar('<'), opt(Separator::parse)),
62 separated_pair(
63 FieldTypeRef::parse,
64 tuple((opt(Separator::parse), cchar(','), opt(Separator::parse))),
65 FieldTypeRef::parse,
66 ),
67 pair(opt(Separator::parse), cchar('>')),
68 ),
69 ),
70 |(k, v)| Self::Map(Box::new(k), Box::new(v)),
71 ),
72 map(
73 preceded(
74 tuple((
75 tag("set"),
76 opt(Separator::parse),
77 opt(terminated(CppTypeRef::parse, opt(Separator::parse))),
78 )),
79 delimited(
80 pair(cchar('<'), opt(Separator::parse)),
81 FieldTypeRef::parse,
82 pair(opt(Separator::parse), cchar('>')),
83 ),
84 ),
85 |v| Self::Set(Box::new(v)),
86 ),
87 map(
88 delimited(
89 pair(tag("list"), opt(Separator::parse)),
90 delimited(
91 pair(cchar('<'), opt(Separator::parse)),
92 FieldTypeRef::parse,
93 pair(opt(Separator::parse), cchar('>')),
94 ),
95 opt(pair(opt(Separator::parse), CppTypeRef::parse)),
96 ),
97 |v| Self::List(Box::new(v)),
98 ),
99 map(IdentifierRef::parse, Self::Identifier),
100 ))(input)
101 }
102
103 pub fn parse_identifier_type(input: &'a str) -> IResult<&'a str, Self> {
104 map(IdentifierRef::parse, Self::Identifier)(input)
105 }
106}
107
108impl<'a> Parser<'a> for FieldTypeRef<'a> {
109 fn parse(input: &'a str) -> IResult<&'a str, Self> {
110 alt((
111 Self::parse_base_type,
112 Self::parse_container_type,
113 Self::parse_identifier_type,
114 ))(input)
115 }
116}
117
118#[derive(Debug, Clone, PartialEq)]
119pub enum FieldType {
120 Identifier(Identifier),
121 Bool,
122 Byte,
123 I8,
124 I16,
125 I32,
126 I64,
127 Double,
128 String,
129 Binary,
130 Map(Box<FieldType>, Box<FieldType>),
131 Set(Box<FieldType>),
132 List(Box<FieldType>),
133}
134
135impl<'a> From<FieldTypeRef<'a>> for FieldType {
136 fn from(r: FieldTypeRef<'a>) -> Self {
137 match r {
138 FieldTypeRef::Identifier(i) => FieldType::Identifier(i.into()),
139 FieldTypeRef::Bool => FieldType::Bool,
140 FieldTypeRef::Byte => FieldType::Byte,
141 FieldTypeRef::I8 => FieldType::I8,
142 FieldTypeRef::I16 => FieldType::I16,
143 FieldTypeRef::I32 => FieldType::I32,
144 FieldTypeRef::I64 => FieldType::I64,
145 FieldTypeRef::Double => FieldType::Double,
146 FieldTypeRef::String => FieldType::String,
147 FieldTypeRef::Binary => FieldType::Binary,
148 FieldTypeRef::Map(k, v) => {
149 FieldType::Map(Box::new(k.as_ref().into()), Box::new(v.as_ref().into()))
150 }
151 FieldTypeRef::Set(v) => FieldType::Set(Box::new(v.as_ref().into())),
152 FieldTypeRef::List(v) => FieldType::List(Box::new(v.as_ref().into())),
153 }
154 }
155}
156
157impl<'a> From<&FieldTypeRef<'a>> for FieldType {
158 fn from(r: &FieldTypeRef<'a>) -> Self {
159 match r {
160 FieldTypeRef::Identifier(i) => FieldType::Identifier(i.clone().into()),
161 FieldTypeRef::Bool => FieldType::Bool,
162 FieldTypeRef::Byte => FieldType::Byte,
163 FieldTypeRef::I8 => FieldType::I8,
164 FieldTypeRef::I16 => FieldType::I16,
165 FieldTypeRef::I32 => FieldType::I32,
166 FieldTypeRef::I64 => FieldType::I64,
167 FieldTypeRef::Double => FieldType::Double,
168 FieldTypeRef::String => FieldType::String,
169 FieldTypeRef::Binary => FieldType::Binary,
170 FieldTypeRef::Map(k, v) => {
171 FieldType::Map(Box::new(k.as_ref().into()), Box::new(v.as_ref().into()))
172 }
173 FieldTypeRef::Set(v) => FieldType::Set(Box::new(v.as_ref().into())),
174 FieldTypeRef::List(v) => FieldType::List(Box::new(v.as_ref().into())),
175 }
176 }
177}
178
179impl<'a> Parser<'a> for FieldType {
180 fn parse(input: &'a str) -> IResult<&'a str, Self> {
181 FieldTypeRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
182 }
183}
184
185#[derive(derive_newtype::NewType, Eq, PartialEq, Debug, Clone)]
187pub struct CppTypeRef<'a>(LiteralRef<'a>);
188
189impl<'a> Parser<'a> for CppTypeRef<'a> {
190 fn parse(input: &'a str) -> IResult<&'a str, Self> {
191 map(
192 preceded(
193 tag("cpp_type"),
194 preceded(Separator::parse, LiteralRef::parse),
195 ),
196 Self,
197 )(input)
198 }
199}
200#[derive(derive_newtype::NewType, Eq, PartialEq, Debug, Clone)]
201pub struct CppType(Literal);
202
203impl<'a> From<CppTypeRef<'a>> for CppType {
204 fn from(r: CppTypeRef<'a>) -> Self {
205 Self(r.0.into())
206 }
207}
208
209impl<'a> Parser<'a> for CppType {
210 fn parse(input: &'a str) -> IResult<&'a str, Self> {
211 CppTypeRef::parse(input).map(|(remains, parsed)| (remains, parsed.into()))
212 }
213}
214
215#[cfg(test)]
216mod test {
217 use crate::utils::*;
218
219 use super::*;
220
221 #[test]
222 fn test_cpp_type() {
223 assert_list_eq_with_f(
224 vec!["cpp_type \"MINI-LUST\"", "cpp_type 'ihciah'"],
225 vec![LiteralRef::from("MINI-LUST"), LiteralRef::from("ihciah")],
226 CppTypeRef::parse,
227 CppTypeRef,
228 );
229 }
230
231 #[test]
232 fn test_field_type() {
233 assert_list_eq_with_f(
234 vec!["bool", "i16"],
235 vec![FieldTypeRef::Bool, FieldTypeRef::I16],
236 FieldTypeRef::parse,
237 |x| x,
238 );
239 assert_eq!(
240 FieldTypeRef::parse("map <bool, bool>").unwrap().1,
241 FieldTypeRef::Map(Box::new(FieldTypeRef::Bool), Box::new(FieldTypeRef::Bool))
242 );
243 assert_eq!(
244 FieldTypeRef::parse("map<bool,bool>").unwrap().1,
245 FieldTypeRef::Map(Box::new(FieldTypeRef::Bool), Box::new(FieldTypeRef::Bool))
246 );
247 assert_eq!(
248 FieldTypeRef::parse("set <bool>").unwrap().1,
249 FieldTypeRef::Set(Box::new(FieldTypeRef::Bool))
250 );
251 assert_eq!(
252 FieldTypeRef::parse("set<bool>").unwrap().1,
253 FieldTypeRef::Set(Box::new(FieldTypeRef::Bool))
254 );
255 assert_eq!(
256 FieldTypeRef::parse("list <bool>").unwrap().1,
257 FieldTypeRef::List(Box::new(FieldTypeRef::Bool))
258 );
259 assert_eq!(
260 FieldTypeRef::parse("list<bool>").unwrap().1,
261 FieldTypeRef::List(Box::new(FieldTypeRef::Bool))
262 );
263 assert_eq!(
264 FieldTypeRef::parse("ihc_iah").unwrap().1,
265 FieldTypeRef::Identifier(IdentifierRef::from("ihc_iah"))
266 );
267 }
268}