Skip to main content

ferogram_tl_parser/tl/
parameter.rs

1// Copyright (c) Ankit Chaubey <ankitchaubey.dev@gmail.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3//
4// ferogram: async Telegram MTProto client in Rust
5// https://github.com/ankit-chaubey/ferogram
6//
7// Based on layer: https://github.com/ankit-chaubey/layer
8// Follows official Telegram client behaviour (tdesktop, TDLib).
9//
10// If you use or modify this code, keep this notice at the top of your file
11// and include the LICENSE-MIT or LICENSE-APACHE file from this repository:
12// https://github.com/ankit-chaubey/ferogram
13
14use std::fmt;
15use std::str::FromStr;
16
17use crate::errors::ParamParseError;
18use crate::tl::ParameterType;
19
20/// A single `name:Type` parameter inside a TL definition.
21#[derive(Clone, Debug, PartialEq, Eq, Hash)]
22pub struct Parameter {
23    /// The parameter name as it appears in the TL schema.
24    pub name: String,
25    /// The resolved type of this parameter.
26    pub ty: ParameterType,
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 single parameter token such as `flags:#`, `id:long`, or
39    /// `photo:flags.0?InputPhoto`.
40    ///
41    /// Returns `Err(ParamParseError::TypeDef { name })` for the special
42    /// `{X:Type}` generic-parameter-definition syntax so callers can handle it
43    /// without the overhead of `?`.
44    fn from_str(token: &str) -> Result<Self, Self::Err> {
45        // Generic type-definition `{X:Type}`: not a real parameter
46        if let Some(inner) = token.strip_prefix('{') {
47            return Err(match inner.strip_suffix(":Type}") {
48                Some(name) => ParamParseError::TypeDef { name: name.into() },
49                None => ParamParseError::MissingDef,
50            });
51        }
52
53        let (name, ty_str) = token
54            .split_once(':')
55            .ok_or(ParamParseError::NotImplemented)?;
56
57        if name.is_empty() || ty_str.is_empty() {
58            return Err(ParamParseError::Empty);
59        }
60
61        Ok(Self {
62            name: name.to_owned(),
63            ty: ty_str.parse()?,
64        })
65    }
66}