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)]
198pub struct HaysonNotFoundError {
199 pub table: String,
200 pub key: String,
201}
202
203impl fmt::Display for HaysonNotFoundError {
204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 write!(f, "key \"{}\" is not in table \"{}\"", self.key, self.table)
206 }
207}
208
209impl std::error::Error for HaysonNotFoundError {}
210
211#[derive(Debug, Clone, PartialEq, Eq)]
212pub struct HaysonQueryParseError {
213 pub position: usize,
214 pub reason: String,
215}
216
217impl fmt::Display for HaysonQueryParseError {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 write!(
220 f,
221 "query text is invalid at position {}: {}",
222 self.position, self.reason
223 )
224 }
225}
226
227impl std::error::Error for HaysonQueryParseError {}
228
229#[derive(Debug, Clone, PartialEq, Eq)]
232pub struct HaysonPartitionError {
233 pub table: String,
234 pub field: String,
235 pub reason: String,
236}
237
238impl HaysonPartitionError {
239 pub fn new(table: impl Into<String>, field: impl Into<String>, reason: impl Into<String>) -> Self {
240 HaysonPartitionError {
241 table: table.into(),
242 field: field.into(),
243 reason: reason.into(),
244 }
245 }
246}
247
248impl fmt::Display for HaysonPartitionError {
249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 write!(
251 f,
252 "partition field \"{}\" of table \"{}\": {}",
253 self.field, self.table, self.reason
254 )
255 }
256}
257
258impl std::error::Error for HaysonPartitionError {}
259
260#[derive(Debug, Clone, PartialEq, Eq)]
263pub struct HaysonCipherError {
264 pub table: String,
265 pub field: String,
266 pub reason: String,
267 pub key_id: Option<String>,
268}
269
270impl HaysonCipherError {
271 pub fn new(table: impl Into<String>, field: impl Into<String>, reason: impl Into<String>) -> Self {
272 HaysonCipherError {
273 table: table.into(),
274 field: field.into(),
275 reason: reason.into(),
276 key_id: None,
277 }
278 }
279
280 pub fn with_key_id(mut self, key_id: impl Into<String>) -> Self {
281 self.key_id = Some(key_id.into());
282 self
283 }
284}
285
286impl fmt::Display for HaysonCipherError {
287 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
288 if self.table.is_empty() {
289 write!(f, "cypher configuration {}", self.reason)
290 } else {
291 write!(
292 f,
293 "encrypted field \"{}\" of table \"{}\" {}",
294 self.field, self.table, self.reason
295 )
296 }
297 }
298}
299
300impl std::error::Error for HaysonCipherError {}