Skip to main content

ferogram_tl_parser/
errors.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::num::ParseIntError;
16
17/// Errors produced while parsing a single parameter token.
18#[derive(Clone, Debug, PartialEq)]
19pub enum ParamParseError {
20    /// An empty string was encountered where a name/type was expected.
21    Empty,
22    /// A `{X:Type}` generic type definition (not a real error; used as a signal).
23    TypeDef {
24        /// The name of the generic type parameter (e.g. `"X"` from `{X:Type}`).
25        name: String,
26    },
27    /// A `{…}` block that isn't a valid type definition.
28    MissingDef,
29    /// A flag expression (`name.N?Type`) was malformed.
30    InvalidFlag,
31    /// A generic `<…>` argument was malformed (missing closing `>`).
32    InvalidGeneric,
33    /// A bare `name` with no `:type`: e.g. old-style `? = Int`.
34    NotImplemented,
35}
36
37impl fmt::Display for ParamParseError {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        match self {
40            Self::Empty => write!(f, "empty token"),
41            Self::TypeDef { name } => write!(f, "generic type definition: {name}"),
42            Self::MissingDef => write!(f, "unknown generic or flag definition"),
43            Self::InvalidFlag => write!(f, "invalid flag expression"),
44            Self::InvalidGeneric => write!(f, "invalid generic argument (unclosed `<`)"),
45            Self::NotImplemented => write!(f, "parameter without `:type` is not supported"),
46        }
47    }
48}
49
50impl std::error::Error for ParamParseError {}
51
52/// Errors produced while parsing a complete TL definition.
53#[derive(Debug, PartialEq)]
54pub enum ParseError {
55    /// The input was blank.
56    Empty,
57    /// No `= Type` was found.
58    MissingType,
59    /// The name (before `=`) was missing or had empty namespace components.
60    MissingName,
61    /// The `#id` hex literal was unparseable.
62    InvalidId(ParseIntError),
63    /// A parameter was invalid.
64    InvalidParam(ParamParseError),
65    /// The definition uses a syntax we don't support yet.
66    NotImplemented,
67}
68
69impl fmt::Display for ParseError {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        match self {
72            Self::Empty => write!(f, "empty definition"),
73            Self::MissingType => write!(f, "missing `= Type`"),
74            Self::MissingName => write!(f, "missing or malformed name"),
75            Self::InvalidId(e) => write!(f, "invalid constructor ID: {e}"),
76            Self::InvalidParam(e) => write!(f, "invalid parameter: {e}"),
77            Self::NotImplemented => write!(f, "unsupported TL syntax"),
78        }
79    }
80}
81
82impl std::error::Error for ParseError {
83    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
84        match self {
85            Self::InvalidId(e) => Some(e),
86            Self::InvalidParam(e) => Some(e),
87            _ => None,
88        }
89    }
90}