Skip to main content

trine_kv/
error.rs

1use std::{error, fmt, io};
2
3use crate::options::DurabilityMode;
4
5/// Convenient result alias used by Trine KV APIs.
6pub type Result<T> = std::result::Result<T, Error>;
7
8/// Error returned by database, storage, recovery, and transaction operations.
9#[derive(Debug)]
10#[non_exhaustive]
11pub enum Error {
12    /// Underlying I/O error from the selected storage backend.
13    Io(io::Error),
14    /// Durable data failed an integrity or consistency check.
15    Corruption {
16        /// Human-readable corruption detail.
17        message: String,
18    },
19    /// Bytes could not be decoded as a valid Trine storage record.
20    InvalidFormat {
21        /// Human-readable decode failure detail.
22        message: String,
23    },
24    /// Bytes use a storage format that this crate version does not support.
25    UnsupportedFormat {
26        /// Human-readable unsupported-format detail.
27        message: String,
28    },
29    /// The requested codec is not available in this build.
30    CodecUnavailable {
31        /// Codec name or identifier that was requested.
32        codec: String,
33    },
34    /// An optimistic transaction conflicted with a committed write.
35    Conflict {
36        /// Human-readable conflict detail.
37        message: String,
38    },
39    /// The database was opened read-only and a write was requested.
40    ReadOnly,
41    /// The database handle is closed.
42    Closed,
43    /// The configured runtime cannot accept the requested work now.
44    RuntimeBusy {
45        /// Human-readable runtime capacity detail.
46        message: String,
47    },
48    /// A named bucket required by durable metadata was not found.
49    BucketMissing {
50        /// Missing bucket name.
51        name: String,
52    },
53    /// Options were invalid or inconsistent.
54    InvalidOptions {
55        /// Human-readable options failure detail.
56        message: String,
57    },
58    /// A Trine feature is unavailable in the current runtime or build.
59    Unsupported {
60        /// Feature name that is unavailable.
61        feature: &'static str,
62    },
63    /// The selected storage backend does not provide a required capability.
64    UnsupportedBackend {
65        /// Backend capability that is unavailable.
66        feature: &'static str,
67    },
68    /// The selected storage backend cannot provide the requested durability.
69    UnsupportedDurability {
70        /// Durability mode requested by the caller.
71        requested: DurabilityMode,
72    },
73}
74
75impl Error {
76    /// Creates an unsupported-feature error.
77    #[must_use]
78    pub const fn unsupported(feature: &'static str) -> Self {
79        Self::Unsupported { feature }
80    }
81
82    /// Creates an unsupported-backend error.
83    #[must_use]
84    pub const fn unsupported_backend(feature: &'static str) -> Self {
85        Self::UnsupportedBackend { feature }
86    }
87
88    /// Creates an unsupported-durability error.
89    #[must_use]
90    pub const fn unsupported_durability(requested: DurabilityMode) -> Self {
91        Self::UnsupportedDurability { requested }
92    }
93
94    /// Creates an invalid-options error.
95    #[must_use]
96    pub fn invalid_options(message: impl Into<String>) -> Self {
97        Self::InvalidOptions {
98            message: message.into(),
99        }
100    }
101
102    /// Creates a runtime-busy error.
103    #[must_use]
104    pub fn runtime_busy(message: impl Into<String>) -> Self {
105        Self::RuntimeBusy {
106            message: message.into(),
107        }
108    }
109}
110
111impl fmt::Display for Error {
112    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
113        match self {
114            Self::Io(error) => write!(formatter, "io error: {error}"),
115            Self::Corruption { message } => write!(formatter, "corruption: {message}"),
116            Self::InvalidFormat { message } => write!(formatter, "invalid format: {message}"),
117            Self::UnsupportedFormat { message } => {
118                write!(formatter, "unsupported format: {message}")
119            }
120            Self::CodecUnavailable { codec } => write!(formatter, "codec unavailable: {codec}"),
121            Self::Conflict { message } => write!(formatter, "transaction conflict: {message}"),
122            Self::ReadOnly => formatter.write_str("database is read-only"),
123            Self::Closed => formatter.write_str("database is closed"),
124            Self::RuntimeBusy { message } => write!(formatter, "runtime busy: {message}"),
125            Self::BucketMissing { name } => write!(formatter, "bucket is missing: {name}"),
126            Self::InvalidOptions { message } => write!(formatter, "invalid options: {message}"),
127            Self::Unsupported { feature } => write!(formatter, "unsupported feature: {feature}"),
128            Self::UnsupportedBackend { feature } => {
129                write!(formatter, "unsupported storage backend feature: {feature}")
130            }
131            Self::UnsupportedDurability { requested } => {
132                write!(
133                    formatter,
134                    "unsupported durability mode: {}",
135                    requested.as_str()
136                )
137            }
138        }
139    }
140}
141
142impl error::Error for Error {
143    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
144        match self {
145            Self::Io(error) => Some(error),
146            _ => None,
147        }
148    }
149}
150
151impl From<io::Error> for Error {
152    fn from(error: io::Error) -> Self {
153        Self::Io(error)
154    }
155}