Skip to main content

lxdb_engine/
error.rs

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}