Skip to main content

onlyne_store/
error.rs

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    /// The file is not one this build can open, and `which` names it: `"server"`
10    /// or `"client"`. The reason travels with the error so the sentence can
11    /// name the revision that was found, which is the half an operator acts on.
12    UnsupportedSchema {
13        /// Which database refused the open.
14        which: &'static str,
15        /// What the marker or the table list actually said.
16        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}