Skip to main content

layer_tl_parser/
errors.rs

1// Copyright (c) Ankit Chaubey <ankitchaubey.dev@gmail.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4// NOTE:
5// The "Layer" project is no longer maintained or supported.
6// Its original purpose for personal SDK/APK experimentation and learning
7// has been fulfilled.
8//
9// Please use Ferogram instead:
10// https://github.com/ankit-chaubey/ferogram
11// Ferogram will receive future updates and development, although progress
12// may be slower.
13//
14// Ferogram is an async Telegram MTProto client library written in Rust.
15// Its implementation follows the behaviour of the official Telegram clients,
16// particularly Telegram Desktop and TDLib, and aims to provide a clean and
17// modern async interface for building Telegram clients and tools.
18
19use std::fmt;
20use std::num::ParseIntError;
21
22/// Errors produced while parsing a single parameter token.
23#[derive(Clone, Debug, PartialEq)]
24pub enum ParamParseError {
25    /// An empty string was encountered where a name/type was expected.
26    Empty,
27    /// A `{X:Type}` generic type definition (not a real error; used as a signal).
28    TypeDef {
29        /// The name of the generic type parameter (e.g. `"X"` from `{X:Type}`).
30        name: String,
31    },
32    /// A `{…}` block that isn't a valid type definition.
33    MissingDef,
34    /// A flag expression (`name.N?Type`) was malformed.
35    InvalidFlag,
36    /// A generic `<…>` argument was malformed (missing closing `>`).
37    InvalidGeneric,
38    /// A bare `name` with no `:type`: e.g. old-style `? = Int`.
39    NotImplemented,
40}
41
42impl fmt::Display for ParamParseError {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        match self {
45            Self::Empty => write!(f, "empty token"),
46            Self::TypeDef { name } => write!(f, "generic type definition: {name}"),
47            Self::MissingDef => write!(f, "unknown generic or flag definition"),
48            Self::InvalidFlag => write!(f, "invalid flag expression"),
49            Self::InvalidGeneric => write!(f, "invalid generic argument (unclosed `<`)"),
50            Self::NotImplemented => write!(f, "parameter without `:type` is not supported"),
51        }
52    }
53}
54
55impl std::error::Error for ParamParseError {}
56
57/// Errors produced while parsing a complete TL definition.
58#[derive(Debug, PartialEq)]
59pub enum ParseError {
60    /// The input was blank.
61    Empty,
62    /// No `= Type` was found.
63    MissingType,
64    /// The name (before `=`) was missing or had empty namespace components.
65    MissingName,
66    /// The `#id` hex literal was unparseable.
67    InvalidId(ParseIntError),
68    /// A parameter was invalid.
69    InvalidParam(ParamParseError),
70    /// The definition uses a syntax we don't support yet.
71    NotImplemented,
72}
73
74impl fmt::Display for ParseError {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        match self {
77            Self::Empty => write!(f, "empty definition"),
78            Self::MissingType => write!(f, "missing `= Type`"),
79            Self::MissingName => write!(f, "missing or malformed name"),
80            Self::InvalidId(e) => write!(f, "invalid constructor ID: {e}"),
81            Self::InvalidParam(e) => write!(f, "invalid parameter: {e}"),
82            Self::NotImplemented => write!(f, "unsupported TL syntax"),
83        }
84    }
85}
86
87impl std::error::Error for ParseError {
88    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
89        match self {
90            Self::InvalidId(e) => Some(e),
91            Self::InvalidParam(e) => Some(e),
92            _ => None,
93        }
94    }
95}