1use std::fmt;
10use std::str::FromStr;
11
12use crate::errors::{ParamParseError, ParseError};
13use crate::tl::{Category, Flag, Parameter, ParameterType, Type};
14use crate::utils::infer_id;
15
16#[derive(Debug, PartialEq)]
20pub struct Definition {
21 pub namespace: Vec<String>,
24
25 pub name: String,
27
28 pub id: u32,
33
34 pub params: Vec<Parameter>,
36
37 pub ty: Type,
39
40 pub category: Category,
42}
43
44impl fmt::Display for Definition {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 for ns in self.namespace.iter() {
47 write!(f, "{ns}.")?;
48 }
49 write!(f, "{}#{:x}", self.name, self.id)?;
50
51 let mut type_defs = vec![];
53 for param in self.params.iter() {
54 if let ParameterType::Normal { ty, .. } = ¶m.ty {
55 ty.find_generic_refs(&mut type_defs);
56 }
57 }
58 type_defs.sort_unstable();
59 type_defs.dedup();
60 for type_def in type_defs {
61 write!(f, " {{{type_def}:Type}}")?;
62 }
63
64 for param in self.params.iter() {
65 write!(f, " {param}")?;
66 }
67 write!(f, " = {}", self.ty)?;
68 Ok(())
69 }
70}
71
72impl FromStr for Definition {
73 type Err = ParseError;
74
75 fn from_str(definition: &str) -> Result<Self, Self::Err> {
87 if definition.trim().is_empty() {
88 return Err(ParseError::Empty);
89 }
90
91 let (left, ty) = match definition.split_once('=') {
93 Some((ls, t)) => (ls.trim(), t.trim()),
94 None => return Err(ParseError::MissingType),
95 };
96
97 let mut ty = Type::from_str(ty).map_err(|_| ParseError::MissingType)?;
98
99 let (name, middle) = match left.split_once(|c: char| c.is_whitespace()) {
101 Some((name, middle)) => (name.trim_end(), middle.trim_start()),
102 None => (left, ""),
103 };
104
105 let (name, id) = match name.split_once('#') {
107 Some((name, id)) => (name.trim_end(), Some(id.trim_start())),
108 None => (name, None),
109 };
110
111 let (namespace, name) = match name.rsplit_once('.') {
113 Some((namespace, name)) => (
114 namespace
115 .split('.')
116 .map(|part| part.to_owned())
117 .collect::<Vec<_>>(),
118 name,
119 ),
120 None => (Vec::new(), name),
121 };
122 if namespace.iter().any(|part| part.is_empty()) || name.is_empty() {
123 return Err(ParseError::MissingName);
124 }
125
126 let id = match id {
128 Some(id) => u32::from_str_radix(id, 16).map_err(ParseError::InvalidId)?,
129 None => infer_id(definition),
130 };
131
132 let mut type_defs = vec![];
134 let mut flag_defs = vec![];
135
136 let params = middle
137 .split_whitespace()
138 .map(Parameter::from_str)
139 .filter_map(|p| match p {
140 Err(ParamParseError::TypeDef { name }) => {
143 type_defs.push(name);
144 None
145 }
146
147 Ok(p) => match p {
148 Parameter {
151 ref name,
152 ty: ParameterType::Flags,
153 } => {
154 flag_defs.push(name.clone());
155 Some(Ok(p))
156 }
157
158 Parameter {
160 ty:
161 ParameterType::Normal {
162 ty:
163 Type {
164 ref name,
165 generic_ref: true,
166 ..
167 },
168 ..
169 },
170 ..
171 } if !type_defs.contains(name) => {
172 Some(Err(ParseError::InvalidParam(ParamParseError::MissingDef)))
173 }
174
175 Parameter {
177 ty:
178 ParameterType::Normal {
179 flag: Some(Flag { ref name, .. }),
180 ..
181 },
182 ..
183 } if !flag_defs.contains(name) => {
184 Some(Err(ParseError::InvalidParam(ParamParseError::MissingDef)))
185 }
186
187 p => Some(Ok(p)),
189 },
190
191 Err(ParamParseError::NotImplemented) => Some(Err(ParseError::NotImplemented)),
193
194 Err(x) => Some(Err(ParseError::InvalidParam(x))),
196 })
197 .collect::<Result<_, ParseError>>()?;
198
199 if type_defs.contains(&ty.name) {
202 ty.generic_ref = true;
203 }
204
205 Ok(Definition {
206 namespace,
207 name: name.to_owned(),
208 id,
209 params,
210 ty,
211 category: Category::Types,
212 })
213 }
214}
215
216impl Definition {
217 pub fn full_name(&self) -> String {
219 let mut result = String::with_capacity(
220 self.namespace.iter().map(|ns| ns.len() + 1).sum::<usize>() + self.name.len(),
221 );
222 for ns in self.namespace.iter() {
223 result.push_str(ns);
224 result.push('.');
225 }
226 result.push_str(&self.name);
227 result
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234 use crate::tl::Flag;
235
236 #[test]
237 fn parse_empty_def() {
238 assert_eq!(Definition::from_str(""), Err(ParseError::Empty));
239 }
240
241 #[test]
242 fn parse_bad_id() {
243 let bad = u32::from_str_radix("bar", 16).unwrap_err();
244 let bad_q = u32::from_str_radix("?", 16).unwrap_err();
245 let bad_empty = u32::from_str_radix("", 16).unwrap_err();
246 assert_eq!(
247 Definition::from_str("foo#bar = baz"),
248 Err(ParseError::InvalidId(bad))
249 );
250 assert_eq!(
251 Definition::from_str("foo#? = baz"),
252 Err(ParseError::InvalidId(bad_q))
253 );
254 assert_eq!(
255 Definition::from_str("foo# = baz"),
256 Err(ParseError::InvalidId(bad_empty))
257 );
258 }
259
260 #[test]
261 fn parse_no_name() {
262 assert_eq!(Definition::from_str(" = foo"), Err(ParseError::MissingName));
263 }
264
265 #[test]
266 fn parse_no_type() {
267 assert_eq!(Definition::from_str("foo"), Err(ParseError::MissingType));
268 assert_eq!(Definition::from_str("foo = "), Err(ParseError::MissingType));
269 }
270
271 #[test]
272 fn parse_unimplemented() {
273 assert_eq!(
274 Definition::from_str("int ? = Int"),
275 Err(ParseError::NotImplemented)
276 );
277 }
278
279 #[test]
280 fn parse_override_id() {
281 let def = "rpc_answer_dropped msg_id:long seq_no:int bytes:int = RpcDropAnswer";
282 assert_eq!(Definition::from_str(def).unwrap().id, 0xa43ad8b7);
283
284 let def = "rpc_answer_dropped#123456 msg_id:long seq_no:int bytes:int = RpcDropAnswer";
285 assert_eq!(Definition::from_str(def).unwrap().id, 0x123456);
286 }
287
288 #[test]
289 fn parse_valid_definition() {
290 let def = Definition::from_str("a#1=d").unwrap();
291 assert_eq!(def.name, "a");
292 assert_eq!(def.id, 1);
293 assert_eq!(def.params.len(), 0);
294 assert_eq!(
295 def.ty,
296 Type {
297 namespace: vec![],
298 name: "d".into(),
299 bare: true,
300 generic_ref: false,
301 generic_arg: None,
302 }
303 );
304
305 let def = Definition::from_str("a=d<e>").unwrap();
306 assert_eq!(def.name, "a");
307 assert_ne!(def.id, 0);
308 assert_eq!(def.params.len(), 0);
309 assert_eq!(
310 def.ty,
311 Type {
312 namespace: vec![],
313 name: "d".into(),
314 bare: true,
315 generic_ref: false,
316 generic_arg: Some(Box::new("e".parse().unwrap())),
317 }
318 );
319
320 let def = Definition::from_str("a b:c = d").unwrap();
321 assert_eq!(def.name, "a");
322 assert_ne!(def.id, 0);
323 assert_eq!(def.params.len(), 1);
324 assert_eq!(
325 def.ty,
326 Type {
327 namespace: vec![],
328 name: "d".into(),
329 bare: true,
330 generic_ref: false,
331 generic_arg: None,
332 }
333 );
334
335 let def = Definition::from_str("a#1 {b:Type} c:!b = d").unwrap();
336 assert_eq!(def.name, "a");
337 assert_eq!(def.id, 1);
338 assert_eq!(def.params.len(), 1);
339 assert!(matches!(
340 def.params[0].ty,
341 ParameterType::Normal {
342 ty: Type { generic_ref, .. },
343 ..
344 } if generic_ref
345 ));
346 assert_eq!(
347 def.ty,
348 Type {
349 namespace: vec![],
350 name: "d".into(),
351 bare: true,
352 generic_ref: false,
353 generic_arg: None,
354 }
355 );
356 }
357
358 #[test]
359 fn parse_multiline_definition() {
360 let def = "
361 first#1 lol:param
362 = t;
363 ";
364
365 assert_eq!(Definition::from_str(def).unwrap().id, 1);
366
367 let def = "
368 second#2
369 lol:String
370 = t;
371 ";
372
373 assert_eq!(Definition::from_str(def).unwrap().id, 2);
374
375 let def = "
376 third#3
377
378 lol:String
379
380 =
381 t;
382 ";
383
384 assert_eq!(Definition::from_str(def).unwrap().id, 3);
385 }
386
387 #[test]
388 fn parse_complete() {
389 let def = "ns1.name#123 {X:Type} flags:# pname:flags.10?ns2.Vector<!X> = ns3.Type";
390 assert_eq!(
391 Definition::from_str(def),
392 Ok(Definition {
393 namespace: vec!["ns1".into()],
394 name: "name".into(),
395 id: 0x123,
396 params: vec![
397 Parameter {
398 name: "flags".into(),
399 ty: ParameterType::Flags,
400 },
401 Parameter {
402 name: "pname".into(),
403 ty: ParameterType::Normal {
404 ty: Type {
405 namespace: vec!["ns2".into()],
406 name: "Vector".into(),
407 bare: false,
408 generic_ref: false,
409 generic_arg: Some(Box::new(Type {
410 namespace: vec![],
411 name: "X".into(),
412 bare: false,
413 generic_ref: true,
414 generic_arg: None,
415 })),
416 },
417 flag: Some(Flag {
418 name: "flags".into(),
419 index: 10
420 })
421 },
422 },
423 ],
424 ty: Type {
425 namespace: vec!["ns3".into()],
426 name: "Type".into(),
427 bare: false,
428 generic_ref: false,
429 generic_arg: None,
430 },
431 category: Category::Types,
432 })
433 );
434 }
435
436 #[test]
437 fn parse_missing_generic() {
438 let def = "name param:!X = Type";
439 assert_eq!(
440 Definition::from_str(def),
441 Err(ParseError::InvalidParam(ParamParseError::MissingDef))
442 );
443
444 let def = "name {X:Type} param:!Y = Type";
445 assert_eq!(
446 Definition::from_str(def),
447 Err(ParseError::InvalidParam(ParamParseError::MissingDef))
448 );
449 }
450
451 #[test]
452 fn parse_unknown_flags() {
453 let def = "name param:flags.0?true = Type";
454 assert_eq!(
455 Definition::from_str(def),
456 Err(ParseError::InvalidParam(ParamParseError::MissingDef))
457 );
458
459 let def = "name foo:# param:flags.0?true = Type";
460 assert_eq!(
461 Definition::from_str(def),
462 Err(ParseError::InvalidParam(ParamParseError::MissingDef))
463 );
464 }
465
466 #[test]
467 fn test_to_string() {
468 let def = "ns1.name#123 {X:Type} flags:# pname:flags.10?ns2.Vector<!X> = ns3.Type";
469 assert_eq!(Definition::from_str(def).unwrap().to_string(), def);
470 }
471}