1use std::{error::Error, fmt, str::Utf8Error};
2
3use lxdb_format::FormatError;
4
5#[derive(Debug)]
6pub enum EngineError {
7 Format(FormatError),
8
9 TokenStringOutOfBounds { token_id: u32, offset: u64, length: u32, table_length: usize },
10
11 InvalidTokenUtf8 { token_id: u32, source: Utf8Error },
12
13 MissingAdjacency { token_id: u32, adjacency_count: usize },
14
15 RelationRangeOutOfBounds { token_id: u32, offset: u64, count: u32, relation_count: usize },
16
17 MissingRelationSource { relation_id: u32, token_id: u32 },
18
19 MissingRelationTarget { relation_id: u32, token_id: u32 },
20}
21
22impl fmt::Display for EngineError {
23 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
24 match self {
25 Self::Format(error) => {
26 write!(formatter, "failed to decode binary record: {error}",)
27 }
28
29 Self::TokenStringOutOfBounds { token_id, offset, length, table_length } => {
30 write!(
31 formatter,
32 "token {token_id} references string range \
33 {offset}..{} outside a table of \
34 {table_length} bytes",
35 offset.saturating_add(u64::from(*length)),
36 )
37 }
38
39 Self::InvalidTokenUtf8 { token_id, source } => {
40 write!(
41 formatter,
42 "token {token_id} contains invalid UTF-8: \
43 {source}",
44 )
45 }
46
47 Self::MissingAdjacency { token_id, adjacency_count } => {
48 write!(
49 formatter,
50 "token {token_id} has no adjacency record; \
51 dataset contains {adjacency_count} adjacency \
52 records",
53 )
54 }
55
56 Self::RelationRangeOutOfBounds { token_id, offset, count, relation_count } => {
57 write!(
58 formatter,
59 "token {token_id} references relation range \
60 {offset}..{} outside a relation table \
61 containing {relation_count} records",
62 offset.saturating_add(u64::from(*count)),
63 )
64 }
65
66 Self::MissingRelationSource { relation_id, token_id } => {
67 write!(
68 formatter,
69 "relation {relation_id} references missing source token \
70 {token_id}",
71 )
72 }
73
74 Self::MissingRelationTarget { relation_id, token_id } => {
75 write!(
76 formatter,
77 "relation {relation_id} references missing target token \
78 {token_id}",
79 )
80 }
81 }
82 }
83}
84
85impl Error for EngineError {
86 fn source(&self) -> Option<&(dyn Error + 'static)> {
87 match self {
88 Self::Format(error) => Some(error),
89
90 Self::InvalidTokenUtf8 { source, .. } => Some(source),
91
92 Self::TokenStringOutOfBounds { .. }
93 | Self::MissingAdjacency { .. }
94 | Self::RelationRangeOutOfBounds { .. }
95 | Self::MissingRelationSource { .. }
96 | Self::MissingRelationTarget { .. } => None,
97 }
98 }
99}
100
101impl From<FormatError> for EngineError {
102 fn from(error: FormatError) -> Self {
103 Self::Format(error)
104 }
105}