Skip to main content

ferogram_tl_parser/
errors.rs

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