1use std::fmt;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct HaysonSchemaError(pub String);
5
6impl fmt::Display for HaysonSchemaError {
7 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8 write!(f, "{}", self.0)
9 }
10}
11
12impl std::error::Error for HaysonSchemaError {}
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct ValidationIssue {
16 pub field: String,
17 pub reason: String,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct HaysonValidationError {
22 pub table: String,
23 pub issues: Vec<ValidationIssue>,
24}
25
26impl fmt::Display for HaysonValidationError {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 let detail = self
29 .issues
30 .iter()
31 .map(|issue| format!("{}: {}", issue.field, issue.reason))
32 .collect::<Vec<_>>()
33 .join("; ");
34 write!(f, "record rejected by schema of table \"{}\" — {}", self.table, detail)
35 }
36}
37
38impl std::error::Error for HaysonValidationError {}
39
40#[derive(Debug, Clone, PartialEq, Eq)]
41pub struct HaysonUniqueViolationError {
42 pub table: String,
43 pub field: String,
44 pub holder: String,
45}
46
47impl fmt::Display for HaysonUniqueViolationError {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 write!(
50 f,
51 "unique field \"{}\" of table \"{}\" is already taken by key \"{}\"",
52 self.field, self.table, self.holder
53 )
54 }
55}
56
57impl std::error::Error for HaysonUniqueViolationError {}
58
59#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct HaysonPendingConflictError {
61 pub table: String,
62 pub key: String,
63 pub fields: Vec<String>,
64}
65
66impl fmt::Display for HaysonPendingConflictError {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 let list = self
69 .fields
70 .iter()
71 .map(|field| format!("\"{field}\""))
72 .collect::<Vec<_>>()
73 .join(", ");
74 write!(
75 f,
76 "key \"{}\" of table \"{}\" already has a queued change on {} — pass force to overwrite it",
77 self.key, self.table, list
78 )
79 }
80}
81
82impl std::error::Error for HaysonPendingConflictError {}
83
84#[derive(Debug, Clone, PartialEq, Eq)]
85pub struct HaysonCorruptLogError {
86 pub path: String,
87 pub offset: u64,
88 pub reason: String,
89}
90
91impl fmt::Display for HaysonCorruptLogError {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 write!(
94 f,
95 "log \"{}\" is corrupt at offset {}: {}",
96 self.path, self.offset, self.reason
97 )
98 }
99}
100
101impl std::error::Error for HaysonCorruptLogError {}
102
103#[derive(Debug, Clone, PartialEq, Eq)]
104pub struct HaysonIndexMismatchError {
105 pub path: String,
106 pub log_path: String,
109 pub watermark: u64,
112 pub expected_hash: String,
113 pub actual_hash: String,
114}
115
116impl fmt::Display for HaysonIndexMismatchError {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 write!(
119 f,
120 "snapshot \"{}\" claims watermark and schema match the log, but its content fingerprint ({}) does not match the log's ({}) — left on disk for inspection, not silently discarded",
121 self.path, self.expected_hash, self.actual_hash
122 )
123 }
124}
125
126impl std::error::Error for HaysonIndexMismatchError {}
127
128#[derive(Debug, Clone, PartialEq, Eq)]
129pub struct HaysonNotFoundError {
130 pub table: String,
131 pub key: String,
132}
133
134impl fmt::Display for HaysonNotFoundError {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 write!(f, "key \"{}\" is not in table \"{}\"", self.key, self.table)
137 }
138}
139
140impl std::error::Error for HaysonNotFoundError {}
141
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub struct HaysonQueryParseError {
144 pub position: usize,
145 pub reason: String,
146}
147
148impl fmt::Display for HaysonQueryParseError {
149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150 write!(
151 f,
152 "query text is invalid at position {}: {}",
153 self.position, self.reason
154 )
155 }
156}
157
158impl std::error::Error for HaysonQueryParseError {}
159
160#[derive(Debug, Clone, PartialEq, Eq)]
163pub struct HaysonPartitionError {
164 pub table: String,
165 pub field: String,
166 pub reason: String,
167}
168
169impl HaysonPartitionError {
170 pub fn new(table: impl Into<String>, field: impl Into<String>, reason: impl Into<String>) -> Self {
171 HaysonPartitionError {
172 table: table.into(),
173 field: field.into(),
174 reason: reason.into(),
175 }
176 }
177}
178
179impl fmt::Display for HaysonPartitionError {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 write!(
182 f,
183 "partition field \"{}\" of table \"{}\": {}",
184 self.field, self.table, self.reason
185 )
186 }
187}
188
189impl std::error::Error for HaysonPartitionError {}
190
191#[derive(Debug, Clone, PartialEq, Eq)]
194pub struct HaysonCipherError {
195 pub table: String,
196 pub field: String,
197 pub reason: String,
198 pub key_id: Option<String>,
199}
200
201impl HaysonCipherError {
202 pub fn new(table: impl Into<String>, field: impl Into<String>, reason: impl Into<String>) -> Self {
203 HaysonCipherError {
204 table: table.into(),
205 field: field.into(),
206 reason: reason.into(),
207 key_id: None,
208 }
209 }
210
211 pub fn with_key_id(mut self, key_id: impl Into<String>) -> Self {
212 self.key_id = Some(key_id.into());
213 self
214 }
215}
216
217impl fmt::Display for HaysonCipherError {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 if self.table.is_empty() {
220 write!(f, "cypher configuration {}", self.reason)
221 } else {
222 write!(
223 f,
224 "encrypted field \"{}\" of table \"{}\" {}",
225 self.field, self.table, self.reason
226 )
227 }
228 }
229}
230
231impl std::error::Error for HaysonCipherError {}