Skip to main content

ferogram_tl_parser/
errors.rs

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