kevy_store/error.rs
1//! [`KevyError`] — the single error type of the embeddable stack.
2//!
3//! Defined here because `kevy-store` sits at the bottom of every
4//! consumer's dependency graph (kevy-embedded, kevy-client, kevy-persist,
5//! kevy-rt and the server all already depend on it) and is the source of
6//! the dominant structured error, [`StoreError`]. Hosting the unified
7//! type here adds no dependency edge anywhere; the protocol crate
8//! (`kevy-resp`) hosting it would require a protocol → store edge.
9
10#[cfg(not(feature = "std"))]
11use crate::nostd_prelude::*;
12use crate::StoreError;
13use core::fmt;
14#[cfg(feature = "std")]
15use std::io;
16
17/// Unified result alias over [`KevyError`].
18pub type KevyResult<T> = core::result::Result<T, KevyError>;
19
20/// The error type of the embeddable stack: `kevy_embedded::Store` and
21/// `kevy_client::Connection` surfaces return `Result<_, KevyError>`.
22///
23/// Structured errors stay structured — a wrong-type write arrives as
24/// `KevyError::Store(StoreError::WrongType)`, not as stringly `io::Error`
25/// text. `From<io::Error>` / `From<StoreError>` keep `?` ergonomic at
26/// both the OS boundary and the store boundary.
27#[derive(Debug)]
28pub enum KevyError {
29 /// Structured store-semantic error (wrong type, non-integer,
30 /// overflow, out-of-memory, …).
31 Store(StoreError),
32 /// Operating-system / transport failure (file, socket, AOF).
33 #[cfg(feature = "std")]
34 Io(io::Error),
35 /// RESP-level failure on a client link: a server error reply
36 /// (`-ERR …` text preserved verbatim) or a malformed / unexpected
37 /// reply shape.
38 Protocol(String),
39 /// Write rejected: the target is a read-only replica.
40 ReadOnly,
41 /// Invalid argument to a typed API (bad flag combination, empty
42 /// prefix, malformed URL, …). Rejected before touching any state.
43 InvalidInput(String),
44 /// A named object (index, view, required key) doesn't exist.
45 NotFound(String),
46 /// The operation isn't available on this backend or build.
47 Unsupported(String),
48 /// A bounded blocking call ran out its timeout.
49 TimedOut,
50 /// The connection / in-process bus is gone (EOF).
51 Closed,
52}
53
54impl fmt::Display for KevyError {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 match self {
57 Self::Store(e) => write!(f, "store error: {e:?}"),
58 #[cfg(feature = "std")]
59 Self::Io(e) => write!(f, "io error: {e}"),
60 Self::Protocol(msg) => write!(f, "protocol error: {msg}"),
61 Self::ReadOnly => {
62 write!(f, "READONLY You can't write against a read only replica")
63 }
64 Self::InvalidInput(msg) => write!(f, "invalid input: {msg}"),
65 Self::NotFound(what) => write!(f, "not found: {what}"),
66 Self::Unsupported(msg) => write!(f, "unsupported: {msg}"),
67 Self::TimedOut => write!(f, "timed out"),
68 Self::Closed => write!(f, "connection closed"),
69 }
70 }
71}
72
73impl core::error::Error for KevyError {
74 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
75 match self {
76 #[cfg(feature = "std")]
77 Self::Io(e) => Some(e),
78 _ => None,
79 }
80 }
81}
82
83impl From<StoreError> for KevyError {
84 fn from(e: StoreError) -> Self {
85 Self::Store(e)
86 }
87}
88
89#[cfg(feature = "std")]
90impl From<io::Error> for KevyError {
91 fn from(e: io::Error) -> Self {
92 Self::Io(e)
93 }
94}