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