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)]
62pub struct HaysonRelationViolationError {
63 pub relation: String,
64 pub table: String,
65 pub field: String,
66 pub value: String,
67}
68
69impl fmt::Display for HaysonRelationViolationError {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 write!(
72 f,
73 "relation \"{}\" refuses \"{}\".\"{}\" = {}: no record on the other side of the relation matches it",
74 self.relation, self.table, self.field, self.value
75 )
76 }
77}
78
79impl std::error::Error for HaysonRelationViolationError {}
80
81#[derive(Debug, Clone, PartialEq, Eq)]
85pub struct HaysonRelationRestrictError {
86 pub relation: String,
87 pub table: String,
88 pub key: String,
89 pub referencing_table: String,
90 pub referencing_field: String,
91 pub referencing: usize,
92}
93
94impl fmt::Display for HaysonRelationRestrictError {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 write!(
97 f,
98 "relation \"{}\" refuses deleting \"{}\".\"{}\": {} record(s) of \"{}\" still point at it through \"{}\"",
99 self.relation, self.table, self.key, self.referencing, self.referencing_table, self.referencing_field
100 )
101 }
102}
103
104impl std::error::Error for HaysonRelationRestrictError {}
105
106#[derive(Debug, Clone, PartialEq, Eq)]
107pub struct HaysonPendingConflictError {
108 pub table: String,
109 pub key: String,
110 pub fields: Vec<String>,
111}
112
113impl fmt::Display for HaysonPendingConflictError {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 let list = self
116 .fields
117 .iter()
118 .map(|field| format!("\"{field}\""))
119 .collect::<Vec<_>>()
120 .join(", ");
121 write!(
122 f,
123 "key \"{}\" of table \"{}\" already has a queued change on {} — pass force to overwrite it",
124 self.key, self.table, list
125 )
126 }
127}
128
129impl std::error::Error for HaysonPendingConflictError {}
130
131#[derive(Debug, Clone, PartialEq, Eq)]
132pub struct HaysonCorruptLogError {
133 pub path: String,
134 pub offset: u64,
135 pub reason: String,
136}
137
138impl fmt::Display for HaysonCorruptLogError {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 write!(
141 f,
142 "log \"{}\" is corrupt at offset {}: {}",
143 self.path, self.offset, self.reason
144 )
145 }
146}
147
148impl std::error::Error for HaysonCorruptLogError {}
149
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub struct HaysonIndexMismatchError {
152 pub path: String,
153 pub log_path: String,
156 pub watermark: u64,
159 pub expected_hash: String,
160 pub actual_hash: String,
161}
162
163impl fmt::Display for HaysonIndexMismatchError {
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 write!(
166 f,
167 "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",
168 self.path, self.expected_hash, self.actual_hash
169 )
170 }
171}
172
173impl std::error::Error for HaysonIndexMismatchError {}
174
175#[derive(Debug, Clone, PartialEq, Eq)]
181pub struct HaysonLogReplacedError {
182 pub path: String,
183}
184
185impl fmt::Display for HaysonLogReplacedError {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 write!(
188 f,
189 "log file \"{}\" was replaced on disk while this database held it open — reopen the database before writing again",
190 self.path
191 )
192 }
193}
194
195impl std::error::Error for HaysonLogReplacedError {}
196
197#[derive(Debug, Clone, PartialEq, Eq)]
202pub struct HaysonImageClashError {
203 pub physical_path: String,
204}
205
206impl fmt::Display for HaysonImageClashError {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208 write!(
209 f,
210 "image bytes differ from the stored file \"{}\" that has the same content hash — refusing to replace it",
211 self.physical_path
212 )
213 }
214}
215
216impl std::error::Error for HaysonImageClashError {}
217
218#[derive(Debug, Clone, PartialEq, Eq)]
219pub struct HaysonNotFoundError {
220 pub table: String,
221 pub key: String,
222}
223
224impl fmt::Display for HaysonNotFoundError {
225 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226 write!(f, "key \"{}\" is not in table \"{}\"", self.key, self.table)
227 }
228}
229
230impl std::error::Error for HaysonNotFoundError {}
231
232#[derive(Debug, Clone, PartialEq, Eq)]
233pub struct HaysonQueryParseError {
234 pub position: usize,
235 pub reason: String,
236}
237
238impl fmt::Display for HaysonQueryParseError {
239 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240 write!(
241 f,
242 "query text is invalid at position {}: {}",
243 self.position, self.reason
244 )
245 }
246}
247
248impl std::error::Error for HaysonQueryParseError {}
249
250#[derive(Debug, Clone, PartialEq, Eq)]
253pub struct HaysonPartitionError {
254 pub table: String,
255 pub field: String,
256 pub reason: String,
257}
258
259impl HaysonPartitionError {
260 pub fn new(table: impl Into<String>, field: impl Into<String>, reason: impl Into<String>) -> Self {
261 HaysonPartitionError {
262 table: table.into(),
263 field: field.into(),
264 reason: reason.into(),
265 }
266 }
267}
268
269impl fmt::Display for HaysonPartitionError {
270 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271 write!(
272 f,
273 "partition field \"{}\" of table \"{}\": {}",
274 self.field, self.table, self.reason
275 )
276 }
277}
278
279impl std::error::Error for HaysonPartitionError {}
280
281#[derive(Debug, Clone, PartialEq, Eq)]
284pub struct HaysonCipherError {
285 pub table: String,
286 pub field: String,
287 pub reason: String,
288 pub key_id: Option<String>,
289}
290
291impl HaysonCipherError {
292 pub fn new(table: impl Into<String>, field: impl Into<String>, reason: impl Into<String>) -> Self {
293 HaysonCipherError {
294 table: table.into(),
295 field: field.into(),
296 reason: reason.into(),
297 key_id: None,
298 }
299 }
300
301 pub fn with_key_id(mut self, key_id: impl Into<String>) -> Self {
302 self.key_id = Some(key_id.into());
303 self
304 }
305}
306
307impl fmt::Display for HaysonCipherError {
308 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309 if self.table.is_empty() {
310 write!(f, "cypher configuration {}", self.reason)
311 } else {
312 write!(
313 f,
314 "encrypted field \"{}\" of table \"{}\" {}",
315 self.field, self.table, self.reason
316 )
317 }
318 }
319}
320
321impl std::error::Error for HaysonCipherError {}