1use std::fmt;
2
3use onlyne_proto::text::{SchemaMismatch, unsupported_schema_message};
4
5pub type StoreResult<T> = std::result::Result<T, StoreError>;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum StoreError {
9 UnsupportedSchema {
13 which: &'static str,
15 mismatch: SchemaMismatch,
17 },
18 NotFound,
19 Busy,
20 Sqlite(String),
21 Serialization(String),
22 InvalidState {
23 from: String,
24 to: String,
25 },
26}
27
28impl StoreError {
29 pub(crate) fn unsupported_schema(which: &'static str, mismatch: SchemaMismatch) -> Self {
30 StoreError::UnsupportedSchema { which, mismatch }
31 }
32}
33
34impl fmt::Display for StoreError {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 match self {
37 StoreError::UnsupportedSchema { which, mismatch } => {
38 f.write_str(&unsupported_schema_message(which, mismatch))
39 }
40 StoreError::NotFound => f.write_str("not found"),
41 StoreError::Busy => f.write_str("database busy"),
42 StoreError::Sqlite(message) => write!(f, "sqlite: {message}"),
43 StoreError::Serialization(message) => write!(f, "serialization: {message}"),
44 StoreError::InvalidState { from, to } => {
45 write!(f, "invalid ledger state transition {from} -> {to}")
46 }
47 }
48 }
49}
50
51impl std::error::Error for StoreError {}
52
53impl From<rusqlite::Error> for StoreError {
54 fn from(value: rusqlite::Error) -> Self {
55 match &value {
56 rusqlite::Error::SqliteFailure(err, _) => match err.code {
57 rusqlite::ErrorCode::DatabaseBusy | rusqlite::ErrorCode::DatabaseLocked => {
58 StoreError::Busy
59 }
60 _ => StoreError::Sqlite(value.to_string()),
61 },
62 _ => StoreError::Sqlite(value.to_string()),
63 }
64 }
65}
66
67impl From<serde_json::Error> for StoreError {
68 fn from(value: serde_json::Error) -> Self {
69 StoreError::Serialization(value.to_string())
70 }
71}
72
73impl From<chrono::ParseError> for StoreError {
74 fn from(value: chrono::ParseError) -> Self {
75 StoreError::Serialization(value.to_string())
76 }
77}