Skip to main content

scythe_core/
errors.rs

1use std::fmt;
2
3#[derive(Debug)]
4pub struct ScytheError {
5    pub code: ErrorCode,
6    pub message: String,
7}
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum ErrorCode {
11    SyntaxError,
12    UnknownTable,
13    UnknownColumn,
14    UnknownFunction,
15    AmbiguousColumn,
16    TypeMismatch,
17    MissingAnnotation,
18    InvalidAnnotation,
19    ColumnCountMismatch,
20    DuplicateAlias,
21    InvalidRecursion,
22    InternalError,
23}
24
25impl fmt::Display for ErrorCode {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        match self {
28            ErrorCode::SyntaxError => write!(f, "SYNTAX_ERROR"),
29            ErrorCode::UnknownTable => write!(f, "UNKNOWN_TABLE"),
30            ErrorCode::UnknownColumn => write!(f, "UNKNOWN_COLUMN"),
31            ErrorCode::UnknownFunction => write!(f, "UNKNOWN_FUNCTION"),
32            ErrorCode::AmbiguousColumn => write!(f, "AMBIGUOUS_COLUMN"),
33            ErrorCode::TypeMismatch => write!(f, "TYPE_MISMATCH"),
34            ErrorCode::MissingAnnotation => write!(f, "MISSING_ANNOTATION"),
35            ErrorCode::InvalidAnnotation => write!(f, "INVALID_ANNOTATION"),
36            ErrorCode::ColumnCountMismatch => write!(f, "COLUMN_COUNT_MISMATCH"),
37            ErrorCode::DuplicateAlias => write!(f, "DUPLICATE_ALIAS"),
38            ErrorCode::InvalidRecursion => write!(f, "INVALID_RECURSION"),
39            ErrorCode::InternalError => write!(f, "INTERNAL_ERROR"),
40        }
41    }
42}
43
44impl fmt::Display for ScytheError {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        write!(f, "{}: {}", self.code, self.message)
47    }
48}
49
50impl std::error::Error for ScytheError {}
51
52impl ScytheError {
53    pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
54        Self {
55            code,
56            message: message.into(),
57        }
58    }
59
60    pub fn syntax(msg: impl Into<String>) -> Self {
61        Self::new(ErrorCode::SyntaxError, msg)
62    }
63
64    pub fn unknown_table(name: &str) -> Self {
65        Self::new(
66            ErrorCode::UnknownTable,
67            format!("table \"{name}\" does not exist"),
68        )
69    }
70
71    pub fn unknown_column(name: &str) -> Self {
72        Self::new(
73            ErrorCode::UnknownColumn,
74            format!("column \"{name}\" does not exist"),
75        )
76    }
77
78    pub fn unknown_function(name: &str) -> Self {
79        Self::new(
80            ErrorCode::UnknownFunction,
81            format!("function \"{name}\" does not exist"),
82        )
83    }
84
85    pub fn ambiguous_column(name: &str) -> Self {
86        Self::new(
87            ErrorCode::AmbiguousColumn,
88            format!("column \"{name}\" is ambiguous"),
89        )
90    }
91
92    pub fn type_mismatch(msg: impl Into<String>) -> Self {
93        Self::new(ErrorCode::TypeMismatch, msg)
94    }
95
96    pub fn missing_annotation(what: &str) -> Self {
97        Self::new(
98            ErrorCode::MissingAnnotation,
99            format!("missing @{what} annotation"),
100        )
101    }
102
103    pub fn invalid_annotation(msg: impl Into<String>) -> Self {
104        Self::new(ErrorCode::InvalidAnnotation, msg)
105    }
106
107    pub fn column_count_mismatch(left: usize, right: usize) -> Self {
108        Self::new(
109            ErrorCode::ColumnCountMismatch,
110            format!("column count mismatch: {left} vs {right}"),
111        )
112    }
113
114    pub fn duplicate_alias(name: &str) -> Self {
115        Self::new(
116            ErrorCode::DuplicateAlias,
117            format!("duplicate column alias \"{name}\""),
118        )
119    }
120
121    pub fn invalid_recursion(msg: impl Into<String>) -> Self {
122        Self::new(ErrorCode::InvalidRecursion, msg)
123    }
124}