Skip to main content

tdlib_rs_parser/tl/
parameter.rs

1// Copyright 2020 - developers of the `grammers` project.
2// Copyright 2022 - developers of the `tdlib-rs` project.
3// Copyright 2024 - developers of the `tgt` and `tdlib-rs` projects.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10use std::fmt;
11use std::str::FromStr;
12
13use crate::errors::ParamParseError;
14use crate::tl::Type;
15
16/// A single parameter, with a name and a type.
17#[derive(Debug, PartialEq)]
18pub struct Parameter {
19    /// The name of the parameter.
20    pub name: String,
21
22    /// The type of the parameter.
23    pub ty: Type,
24
25    /// The description of the parameter.
26    pub description: String,
27}
28
29impl fmt::Display for Parameter {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        write!(f, "{}:{}", self.name, self.ty)
32    }
33}
34
35impl FromStr for Parameter {
36    type Err = ParamParseError;
37
38    /// Parses a parameter.
39    ///
40    /// # Examples
41    ///
42    /// ```
43    /// use tdlib_rs_parser::tl::Parameter;
44    ///
45    /// assert!("foo:Bar".parse::<Parameter>().is_ok());
46    /// ```
47    fn from_str(param: &str) -> Result<Self, Self::Err> {
48        // Parse `name:type`
49        let (name, ty) = {
50            let mut it = param.split(':');
51            if let Some(n) = it.next() {
52                if let Some(t) = it.next() {
53                    (n, t)
54                } else {
55                    return Err(ParamParseError::NotImplemented);
56                }
57            } else {
58                return Err(ParamParseError::Empty);
59            }
60        };
61
62        if name.is_empty() {
63            return Err(ParamParseError::Empty);
64        }
65
66        Ok(Parameter {
67            name: name.into(),
68            ty: ty.parse()?,
69            description: String::new(),
70        })
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use crate::tl::Type;
78
79    #[test]
80    fn parse_empty_param() {
81        assert_eq!(Parameter::from_str(":noname"), Err(ParamParseError::Empty));
82        assert_eq!(Parameter::from_str("notype:"), Err(ParamParseError::Empty));
83        assert_eq!(Parameter::from_str(":"), Err(ParamParseError::Empty));
84    }
85
86    #[test]
87    fn parse_unknown_param() {
88        assert_eq!(
89            Parameter::from_str(""),
90            Err(ParamParseError::NotImplemented)
91        );
92        assert_eq!(
93            Parameter::from_str("no colon"),
94            Err(ParamParseError::NotImplemented)
95        );
96        assert_eq!(
97            Parameter::from_str("colonless"),
98            Err(ParamParseError::NotImplemented)
99        );
100    }
101
102    #[test]
103    fn parse_bad_generics() {
104        assert_eq!(
105            Parameter::from_str("foo:<bar"),
106            Err(ParamParseError::InvalidGeneric)
107        );
108        assert_eq!(
109            Parameter::from_str("foo:bar<"),
110            Err(ParamParseError::InvalidGeneric)
111        );
112    }
113
114    #[test]
115    fn parse_valid_param() {
116        assert_eq!(
117            Parameter::from_str("foo:bar<baz>"),
118            Ok(Parameter {
119                name: "foo".into(),
120                ty: Type {
121                    name: "bar".into(),
122                    bare: true,
123                    generic_arg: Some(Box::new("baz".parse().unwrap())),
124                },
125                description: String::new(),
126            })
127        );
128    }
129}