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}