wowdbdefs_rs/
error.rs

1//! Error types for the crate.
2//!
3use std::fmt::{Display, Formatter};
4
5/// Main error for parsing the files.
6#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
7pub struct ParseError {
8    /// Amount of characters into the line the error starts on.
9    pub column: usize,
10    /// Line number the error starts on. Starts at 1.
11    pub line: usize,
12    /// Reason for error.
13    pub reason: DbdErrorReason,
14}
15
16impl ParseError {
17    pub(crate) const fn new(column: usize, line: usize, reason: DbdErrorReason) -> Self {
18        Self {
19            column,
20            line,
21            reason,
22        }
23    }
24
25    /// Prints `contents` from the `(line, column)` to the end of the string.
26    pub fn start_str_at<'a>(&self, mut contents: &'a str) -> Option<&'a str> {
27        let mut i = 0_usize;
28
29        if self.line == 0 {
30            return Some(&contents[self.column..]);
31        }
32
33        while let Some((_, b)) = contents.split_once('\n') {
34            i += 1;
35
36            if self.line == i {
37                return Some(&b[self.column..]);
38            }
39
40            contents = b;
41        }
42
43        None
44    }
45}
46
47impl Display for ParseError {
48    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
49        f.write_fmt(format_args!(
50            "Column {}, line {}: {}",
51            self.column, self.line, self.reason,
52        ))
53    }
54}
55
56impl std::error::Error for ParseError {}
57
58/// Specific reason the parser failed.
59#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
60pub enum DbdErrorReason {
61    /// The type and name under `COLUMNS` were not separated by a space.
62    NoSpaceInColumn,
63
64    /// The foreign key did not contain a double colon (`::`) in between the delimiters (`<`/`>`).
65    NoDoubleColonInForeignKey,
66    /// The foreign key did not include a closing angle bracket (`>`).
67    NoClosingForeignKeyAngleBracket,
68
69    /// The annotations did not include a closing dollar sign (`$`).
70    NoClosingAnnotationDollarSign,
71
72    /// The integer size did not include a closing angle bracket (`>`).
73    NoClosingIntegerSizeAngleBracket,
74    /// The integer size was not a valid integer.
75    InvalidIntegerSizeNumber(String),
76
77    /// The array size did not include a closing square bracket (`]`).
78    NoClosingArraySizeSquareBracket,
79    /// The array size is not a valid integer.
80    InvalidArraySizeNumber(String),
81
82    /// The layout is not a valid hex string.
83    InvalidLayout(String),
84    /// The build is not a valid build string (`MAJOR.MINOR.PATCH.BUILD`).
85    InvalidBuild(String),
86
87    /// The type name is not valid.
88    InvalidType(String),
89}
90
91impl Display for DbdErrorReason {
92    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
93        let s = match self {
94            DbdErrorReason::NoSpaceInColumn => "no space to separate column name and type",
95            DbdErrorReason::NoDoubleColonInForeignKey => {
96                "no '::' inside foreign key '<' and '>' brackets"
97            }
98            DbdErrorReason::NoClosingForeignKeyAngleBracket => {
99                "no matching '>' for opening '<' in foreign key"
100            }
101            DbdErrorReason::NoClosingAnnotationDollarSign => {
102                "no matching '$' for opening '$' in annotations"
103            }
104            DbdErrorReason::NoClosingArraySizeSquareBracket => {
105                "no matching ']' for opening '[' in array"
106            }
107            DbdErrorReason::NoClosingIntegerSizeAngleBracket => {
108                "no matching '>' for opening '<' in integer size"
109            }
110            DbdErrorReason::InvalidLayout(s) => {
111                return f.write_fmt(format_args!("invalid hex string for layout: '{}'", s));
112            }
113            DbdErrorReason::InvalidIntegerSizeNumber(s) => {
114                return f.write_fmt(format_args!("invalid integer size: '{}'", s));
115            }
116            DbdErrorReason::InvalidArraySizeNumber(s) => {
117                return f.write_fmt(format_args!("invalid array size: '{}'", s));
118            }
119            DbdErrorReason::InvalidType(s) => {
120                return f.write_fmt(format_args!("invalid type name: '{}'", s));
121            }
122            DbdErrorReason::InvalidBuild(s) => {
123                return f.write_fmt(format_args!("invalid build format: '{}'", s));
124            }
125        };
126        f.write_str(s)
127    }
128}
129
130/// Errors for converting from raw types to proper types.
131#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
132pub enum ConversionError {
133    /// The integer width was not either 8, 16, 32 or 64.
134    InvalidIntegerWidth(usize),
135    /// An integer did not have an integer width.
136    NoIntegerWidth,
137
138    /// The corresponding column was not found for an entry.
139    ColumnNotFound(String),
140
141    /// A `locstring` is attempted used as a foreign key.
142    LocStringAsForeignKey,
143    /// A `string` is attempted used as a foreign key.
144    StringAsForeignKey,
145    /// A `float` is attempted used as a foreign key.
146    FloatAsForeignKey,
147}
148
149impl Display for ConversionError {
150    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
151        match self {
152            ConversionError::InvalidIntegerWidth(i) => {
153                write!(f, "invalid integer size '{}'", i)
154            }
155            ConversionError::NoIntegerWidth => write!(f, "no integer width for integer"),
156            ConversionError::ColumnNotFound(s) => write!(f, "column not found '{}'", s),
157            ConversionError::LocStringAsForeignKey => {
158                write!(f, "LocString type is set as foreign key")
159            }
160            ConversionError::StringAsForeignKey => {
161                write!(f, "String type is set as foreign key")
162            }
163            ConversionError::FloatAsForeignKey => {
164                write!(f, "Float type is set as foreign key")
165            }
166        }
167    }
168}
169
170impl std::error::Error for ConversionError {}