tighterror_build/
errors.rs

1//! Crate errors.
2
3/**
4 * Error category type.
5 *
6 * See the [categories] module for category constants.
7*/
8
9#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
10#[repr(transparent)]
11pub struct TbErrorCategory(_p::R);
12
13impl TbErrorCategory {
14    #[inline]
15    const fn new(v: _p::R) -> Self {
16        Self(v)
17    }
18
19    /// Returns the name of the error category.
20    #[inline]
21    pub fn name(&self) -> &'static str {
22        _cn::A[self.0 as usize]
23    }
24}
25
26impl tighterror::Category for TbErrorCategory {
27    type R = _p::R;
28    const BITS: usize = _p::CAT_BITS;
29
30    #[inline]
31    fn name(&self) -> &'static str {
32        self.name()
33    }
34}
35
36impl core::fmt::Display for TbErrorCategory {
37    #[inline]
38    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
39        f.pad(self.name())
40    }
41}
42
43impl core::fmt::Debug for TbErrorCategory {
44    #[inline]
45    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46        f.debug_tuple("TbErrorCategory")
47            .field(&_p::Ident(self.name()))
48            .finish()
49    }
50}
51
52/**
53 * Error kind type.
54 *
55 * See the [kinds] module for error kind constants.
56*/
57
58#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
59#[repr(transparent)]
60pub struct TbErrorKind(_p::R);
61
62impl TbErrorKind {
63    const fn new(cat: TbErrorCategory, variant: _p::R) -> Self {
64        Self(cat.0 << _p::VAR_BITS | variant)
65    }
66
67    #[inline]
68    fn category_value(&self) -> _p::R {
69        (self.0 & _p::CAT_MASK) >> _p::VAR_BITS
70    }
71
72    #[inline]
73    fn variant_value(&self) -> _p::R {
74        self.0 & _p::VAR_MASK
75    }
76
77    /// Returns the error category.
78    #[inline]
79    pub fn category(&self) -> TbErrorCategory {
80        TbErrorCategory::new(self.category_value())
81    }
82
83    /// Returns the error kind name.
84    #[inline]
85    pub fn name(&self) -> &'static str {
86        _n::A[self.category_value() as usize][self.variant_value() as usize]
87    }
88
89    #[inline]
90    fn display(&self) -> &'static str {
91        _d::A[self.category_value() as usize][self.variant_value() as usize]
92    }
93
94    /// Returns the error kind value as the underlying Rust type.
95    #[inline]
96    pub fn value(&self) -> _p::R {
97        self.0
98    }
99
100    /// Creates an error kind from a raw value of the underlying Rust type.
101    #[inline]
102    pub fn from_value(value: _p::R) -> Option<Self> {
103        let cat = (value & _p::CAT_MASK) >> _p::VAR_BITS;
104        let variant = value & _p::VAR_MASK;
105        if cat <= _p::CAT_MAX && variant <= _p::VAR_MAXES[cat as usize] {
106            Some(Self::new(TbErrorCategory::new(cat), variant))
107        } else {
108            None
109        }
110    }
111}
112
113impl tighterror::Kind for TbErrorKind {
114    type R = _p::R;
115    type Category = TbErrorCategory;
116    const BITS: usize = _p::KIND_BITS;
117
118    #[inline]
119    fn category(&self) -> Self::Category {
120        self.category()
121    }
122
123    #[inline]
124    fn name(&self) -> &'static str {
125        self.name()
126    }
127
128    #[inline]
129    fn value(&self) -> Self::R {
130        self.value()
131    }
132
133    #[inline]
134    fn from_value(value: Self::R) -> Option<Self> {
135        Self::from_value(value)
136    }
137}
138
139impl core::fmt::Display for TbErrorKind {
140    #[inline]
141    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
142        f.pad(self.name())
143    }
144}
145
146impl core::fmt::Debug for TbErrorKind {
147    #[inline]
148    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
149        f.debug_struct("TbErrorKind")
150            .field("cat", &_p::Ident(self.category().name()))
151            .field("var", &_p::Ident(self.name()))
152            .field("val", &self.0)
153            .finish()
154    }
155}
156
157impl<T> core::convert::From<TbErrorKind> for Result<T, TbError> {
158    #[inline]
159    fn from(v: TbErrorKind) -> Self {
160        Err(v.into())
161    }
162}
163
164/**
165 * Error type.
166 *
167 * See the [kinds] module for error kind constants.
168*/
169
170#[derive(Debug)]
171#[repr(transparent)]
172pub struct TbError(TbErrorKind);
173
174impl TbError {
175    /// Returns the error kind.
176    #[inline]
177    pub fn kind(&self) -> TbErrorKind {
178        self.0
179    }
180
181    /// Returns the error origin location.
182    #[inline]
183    pub fn location(&self) -> tighterror::Location {
184        tighterror::Location::undefined()
185    }
186}
187
188impl tighterror::Error for TbError {
189    type R = _p::R;
190    type Category = TbErrorCategory;
191    type Kind = TbErrorKind;
192
193    #[inline]
194    fn kind(&self) -> Self::Kind {
195        self.kind()
196    }
197
198    #[inline]
199    fn location(&self) -> tighterror::Location {
200        self.location()
201    }
202}
203
204impl core::convert::From<TbErrorKind> for TbError {
205    #[inline]
206    fn from(kind: TbErrorKind) -> Self {
207        Self(kind)
208    }
209}
210
211impl core::fmt::Display for TbError {
212    #[inline]
213    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
214        f.pad(self.kind().display())
215    }
216}
217
218impl core::cmp::PartialEq for TbError {
219    /// Checks equality based on the error kind only.
220    #[inline]
221    fn eq(&self, other: &TbError) -> bool {
222        self.0 == other.0
223    }
224}
225
226impl<T> core::convert::From<TbError> for core::result::Result<T, TbError> {
227    #[inline]
228    fn from(err: TbError) -> Self {
229        Err(err)
230    }
231}
232
233impl std::error::Error for TbError {}
234
235mod _cn {
236    pub const PARSER: &str = "PARSER";
237    pub const CODER: &str = "CODER";
238    pub static A: [&str; 2] = [PARSER, CODER];
239}
240
241mod _n {
242    pub(crate) mod parser {
243        pub(crate) const BAD_IDENTIFIER_CHARACTERS: &str = "BAD_IDENTIFIER_CHARACTERS";
244        pub(crate) const BAD_IDENTIFIER_CASE: &str = "BAD_IDENTIFIER_CASE";
245        pub(crate) const BAD_KEYWORD_TYPE: &str = "BAD_KEYWORD_TYPE";
246        pub(crate) const BAD_MODULE_IDENTIFIER: &str = "BAD_MODULE_IDENTIFIER";
247        pub(crate) const BAD_NAME: &str = "BAD_NAME";
248        pub(crate) const BAD_OBJECT_ATTRIBUTE: &str = "BAD_OBJECT_ATTRIBUTE";
249        pub(crate) const BAD_SPEC_FILE_EXTENSION: &str = "BAD_SPEC_FILE_EXTENSION";
250        pub(crate) const BAD_TOML: &str = "BAD_TOML";
251        pub(crate) const BAD_ROOT_LEVEL_KEYWORD: &str = "BAD_ROOT_LEVEL_KEYWORD";
252        pub(crate) const BAD_VALUE_TYPE: &str = "BAD_VALUE_TYPE";
253        pub(crate) const BAD_YAML: &str = "BAD_YAML";
254        pub(crate) const EMPTY_IDENTIFIER: &str = "EMPTY_IDENTIFIER";
255        pub(crate) const EMPTY_LIST: &str = "EMPTY_LIST";
256        pub(crate) const FAILED_TO_OPEN_SPEC_FILE: &str = "FAILED_TO_OPEN_SPEC_FILE";
257        pub(crate) const MISSING_ATTRIBUTE: &str = "MISSING_ATTRIBUTE";
258        pub(crate) const MUTUALLY_EXCLUSIVE_KEYWORDS: &str = "MUTUALLY_EXCLUSIVE_KEYWORDS";
259        pub(crate) const NON_UNIQUE_NAME: &str = "NON_UNIQUE_NAME";
260        pub(crate) const SPEC_FILE_NOT_FOUND: &str = "SPEC_FILE_NOT_FOUND";
261        pub(crate) const NAME_COLLISION: &str = "NAME_COLLISION";
262        pub static A: [&str; 19] = [
263            BAD_IDENTIFIER_CHARACTERS,
264            BAD_IDENTIFIER_CASE,
265            BAD_KEYWORD_TYPE,
266            BAD_MODULE_IDENTIFIER,
267            BAD_NAME,
268            BAD_OBJECT_ATTRIBUTE,
269            BAD_SPEC_FILE_EXTENSION,
270            BAD_TOML,
271            BAD_ROOT_LEVEL_KEYWORD,
272            BAD_VALUE_TYPE,
273            BAD_YAML,
274            EMPTY_IDENTIFIER,
275            EMPTY_LIST,
276            FAILED_TO_OPEN_SPEC_FILE,
277            MISSING_ATTRIBUTE,
278            MUTUALLY_EXCLUSIVE_KEYWORDS,
279            NON_UNIQUE_NAME,
280            SPEC_FILE_NOT_FOUND,
281            NAME_COLLISION,
282        ];
283    }
284
285    pub(crate) mod coder {
286        pub(crate) const CATEGORY_REQUIRED: &str = "CATEGORY_REQUIRED";
287        pub(crate) const ERROR_REQUIRED: &str = "ERROR_REQUIRED";
288        pub(crate) const FAILED_TO_PARSE_TOKENS: &str = "FAILED_TO_PARSE_TOKENS";
289        pub(crate) const FAILED_TO_READ_OUTPUT_FILE: &str = "FAILED_TO_READ_OUTPUT_FILE";
290        pub(crate) const FAILED_TO_WRITE_OUTPUT_FILE: &str = "FAILED_TO_WRITE_OUTPUT_FILE";
291        pub(crate) const RUSTFMT_FAILED: &str = "RUSTFMT_FAILED";
292        pub(crate) const RUSTFMT_NOT_FOUND: &str = "RUSTFMT_NOT_FOUND";
293        pub(crate) const TOO_MANY_BITS: &str = "TOO_MANY_BITS";
294        pub(crate) const OUTPUT_PATH_NOT_DIRECTORY: &str = "OUTPUT_PATH_NOT_DIRECTORY";
295        pub static A: [&str; 9] = [
296            CATEGORY_REQUIRED,
297            ERROR_REQUIRED,
298            FAILED_TO_PARSE_TOKENS,
299            FAILED_TO_READ_OUTPUT_FILE,
300            FAILED_TO_WRITE_OUTPUT_FILE,
301            RUSTFMT_FAILED,
302            RUSTFMT_NOT_FOUND,
303            TOO_MANY_BITS,
304            OUTPUT_PATH_NOT_DIRECTORY,
305        ];
306    }
307
308    pub static A: [&[&str]; 2] = [&parser::A, &coder::A];
309}
310
311mod _d {
312    pub(crate) mod parser {
313        pub(crate) const BAD_IDENTIFIER_CHARACTERS: &str =
314            "Identifier contains unsupported characters.";
315        pub(crate) const BAD_IDENTIFIER_CASE: &str =
316            "Identifier is specified in an unsupported case.";
317        pub(crate) const BAD_KEYWORD_TYPE: &str = "Specification keyword is not a String.";
318        pub(crate) const BAD_MODULE_IDENTIFIER: &str = "Identifier is not valid on module-level.";
319        pub(crate) const BAD_NAME: &str = "Invalid name.";
320        pub(crate) const BAD_OBJECT_ATTRIBUTE: &str = "An object attribute is invalid.";
321        pub(crate) const BAD_SPEC_FILE_EXTENSION: &str =
322            "Specification filename extension is not supported or is missing.";
323        pub(crate) const BAD_TOML: &str = "TOML deserialization has failed.";
324        pub(crate) const BAD_ROOT_LEVEL_KEYWORD: &str =
325            "Specification contains an invalid root-level keyword.";
326        pub(crate) const BAD_VALUE_TYPE: &str = "Specification value type is invalid.";
327        pub(crate) const BAD_YAML: &str = "YAML deserialization has failed.";
328        pub(crate) const EMPTY_IDENTIFIER: &str = "An identifier cannot be an empty string.";
329        pub(crate) const EMPTY_LIST: &str = "Empty list of objects is not allowed.";
330        pub(crate) const FAILED_TO_OPEN_SPEC_FILE: &str = "Specification file couldn't be opened.";
331        pub(crate) const MISSING_ATTRIBUTE: &str = "Specification lacks a mandatory attribute.";
332        pub(crate) const MUTUALLY_EXCLUSIVE_KEYWORDS: &str =
333            "Specification contains mutually exclusive keywords.";
334        pub(crate) const NON_UNIQUE_NAME: &str = "A name is not unique.";
335        pub(crate) const SPEC_FILE_NOT_FOUND: &str = "Specification file couldn't be found.";
336        pub(crate) const NAME_COLLISION: &str = "Collision of names between different items.";
337        pub static A: [&str; 19] = [
338            BAD_IDENTIFIER_CHARACTERS,
339            BAD_IDENTIFIER_CASE,
340            BAD_KEYWORD_TYPE,
341            BAD_MODULE_IDENTIFIER,
342            BAD_NAME,
343            BAD_OBJECT_ATTRIBUTE,
344            BAD_SPEC_FILE_EXTENSION,
345            BAD_TOML,
346            BAD_ROOT_LEVEL_KEYWORD,
347            BAD_VALUE_TYPE,
348            BAD_YAML,
349            EMPTY_IDENTIFIER,
350            EMPTY_LIST,
351            FAILED_TO_OPEN_SPEC_FILE,
352            MISSING_ATTRIBUTE,
353            MUTUALLY_EXCLUSIVE_KEYWORDS,
354            NON_UNIQUE_NAME,
355            SPEC_FILE_NOT_FOUND,
356            NAME_COLLISION,
357        ];
358    }
359
360    pub(crate) mod coder {
361        pub(crate) const CATEGORY_REQUIRED: &str = "At least one category must be defined.";
362        pub(crate) const ERROR_REQUIRED: &str = "At least one error must be defined.";
363        pub(crate) const FAILED_TO_PARSE_TOKENS: &str = "Generated code tokens couldn't be parsed.";
364        pub(crate) const FAILED_TO_READ_OUTPUT_FILE: &str = "Output file couldn't be read.";
365        pub(crate) const FAILED_TO_WRITE_OUTPUT_FILE: &str = "Output file couldn't be written.";
366        pub(crate) const RUSTFMT_FAILED: &str = "Rustfmt tool exited with an error.";
367        pub(crate) const RUSTFMT_NOT_FOUND: &str = "Rustfmt tool isn't found.";
368        pub(crate) const TOO_MANY_BITS: &str =
369            "The number of required bits exceeds the largest supported type u64.";
370        pub(crate) const OUTPUT_PATH_NOT_DIRECTORY: &str = "Output path is not a directory.";
371        pub static A: [&str; 9] = [
372            CATEGORY_REQUIRED,
373            ERROR_REQUIRED,
374            FAILED_TO_PARSE_TOKENS,
375            FAILED_TO_READ_OUTPUT_FILE,
376            FAILED_TO_WRITE_OUTPUT_FILE,
377            RUSTFMT_FAILED,
378            RUSTFMT_NOT_FOUND,
379            TOO_MANY_BITS,
380            OUTPUT_PATH_NOT_DIRECTORY,
381        ];
382    }
383
384    pub static A: [&[&str]; 2] = [&parser::A, &coder::A];
385}
386
387mod _p {
388    pub type R = u8;
389    pub const KIND_BITS: usize = 6;
390    pub const CAT_BITS: usize = 1;
391    pub const CAT_MAX: R = 1;
392    pub const VAR_MASK: R = 31;
393    pub static VAR_MAXES: [R; 2] = [18, 8];
394    pub const CAT_MASK: R = 32;
395    pub const VAR_BITS: usize = 5;
396    const _: () = assert!(KIND_BITS <= R::BITS as usize);
397    const _: () = assert!(CAT_BITS <= usize::BITS as usize);
398    pub(super) struct Ident<'a>(pub(super) &'a str);
399
400    impl<'a> core::fmt::Debug for Ident<'a> {
401        #[inline]
402        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
403            f.pad(self.0)
404        }
405    }
406}
407
408/// Error category constants.
409pub mod category {
410    use super::TbErrorCategory as C;
411
412    /// Parser errors category.
413    pub const PARSER: C = C::new(0);
414
415    /// Coder errors category.
416    pub const CODER: C = C::new(1);
417}
418
419/// Error kind constants.
420pub mod kind {
421    use super::category as c;
422    use super::TbErrorKind as EK;
423
424    /// Parser category error kind constants.
425    pub mod parser {
426        use super::c;
427        use super::EK;
428
429        /// Identifier contains unsupported characters.
430        pub const BAD_IDENTIFIER_CHARACTERS: EK = EK::new(c::PARSER, 0);
431
432        /// Identifier is specified in an unsupported case.
433        pub const BAD_IDENTIFIER_CASE: EK = EK::new(c::PARSER, 1);
434
435        /// Specification keyword is not a String.
436        pub const BAD_KEYWORD_TYPE: EK = EK::new(c::PARSER, 2);
437
438        /// Identifier is not valid on module-level.
439        pub const BAD_MODULE_IDENTIFIER: EK = EK::new(c::PARSER, 3);
440
441        /// Invalid name.
442        pub const BAD_NAME: EK = EK::new(c::PARSER, 4);
443
444        /// An object attribute is invalid.
445        pub const BAD_OBJECT_ATTRIBUTE: EK = EK::new(c::PARSER, 5);
446
447        /// Specification filename extension is not supported or is missing.
448        pub const BAD_SPEC_FILE_EXTENSION: EK = EK::new(c::PARSER, 6);
449
450        /// TOML deserialization has failed.
451        pub const BAD_TOML: EK = EK::new(c::PARSER, 7);
452
453        /// Specification contains an invalid root-level keyword.
454        pub const BAD_ROOT_LEVEL_KEYWORD: EK = EK::new(c::PARSER, 8);
455
456        /// Specification value type is invalid.
457        pub const BAD_VALUE_TYPE: EK = EK::new(c::PARSER, 9);
458
459        /// YAML deserialization has failed.
460        pub const BAD_YAML: EK = EK::new(c::PARSER, 10);
461
462        /// An identifier cannot be an empty string.
463        pub const EMPTY_IDENTIFIER: EK = EK::new(c::PARSER, 11);
464
465        /// Empty list of objects is not allowed.
466        pub const EMPTY_LIST: EK = EK::new(c::PARSER, 12);
467
468        /// Specification file couldn't be opened.
469        pub const FAILED_TO_OPEN_SPEC_FILE: EK = EK::new(c::PARSER, 13);
470
471        /// Specification lacks a mandatory attribute.
472        pub const MISSING_ATTRIBUTE: EK = EK::new(c::PARSER, 14);
473
474        /// Specification contains mutually exclusive keywords.
475        pub const MUTUALLY_EXCLUSIVE_KEYWORDS: EK = EK::new(c::PARSER, 15);
476
477        /// A name is not unique.
478        pub const NON_UNIQUE_NAME: EK = EK::new(c::PARSER, 16);
479
480        /// Specification file couldn't be found.
481        pub const SPEC_FILE_NOT_FOUND: EK = EK::new(c::PARSER, 17);
482
483        /// Collision of names between different items.
484        pub const NAME_COLLISION: EK = EK::new(c::PARSER, 18);
485    }
486
487    /// Coder category error kind constants.
488    pub mod coder {
489        use super::c;
490        use super::EK;
491
492        /// At least one category must be defined.
493        pub const CATEGORY_REQUIRED: EK = EK::new(c::CODER, 0);
494
495        /// At least one error must be defined.
496        pub const ERROR_REQUIRED: EK = EK::new(c::CODER, 1);
497
498        /// Generated code tokens couldn't be parsed.
499        pub const FAILED_TO_PARSE_TOKENS: EK = EK::new(c::CODER, 2);
500
501        /// Output file couldn't be read.
502        pub const FAILED_TO_READ_OUTPUT_FILE: EK = EK::new(c::CODER, 3);
503
504        /// Output file couldn't be written.
505        pub const FAILED_TO_WRITE_OUTPUT_FILE: EK = EK::new(c::CODER, 4);
506
507        /// Rustfmt tool exited with an error.
508        pub const RUSTFMT_FAILED: EK = EK::new(c::CODER, 5);
509
510        /// Rustfmt tool isn't found.
511        pub const RUSTFMT_NOT_FOUND: EK = EK::new(c::CODER, 6);
512
513        /// The number of required bits exceeds the largest supported type u64.
514        pub const TOO_MANY_BITS: EK = EK::new(c::CODER, 7);
515
516        /// Output path is not a directory.
517        pub const OUTPUT_PATH_NOT_DIRECTORY: EK = EK::new(c::CODER, 8);
518    }
519}