heaplet 0.1.0

A small, in-process, Redis-inspired in-memory store for Rust.
Documentation
//! Error type returned by heaplet operations.
//!
//! This crate uses a single [`Error`] enum for:
//! - missing keys/elements (`NotFound`)
//! - argument validation (`InvalidArgument`)
//! - type mismatches (`WrongType`)
//! - codec failures (`Encode` / `Decode`)

use core::fmt;

/// Errors returned by heaplet operations.
///
/// Most APIs return `Result<_, Error>`. Common failure modes:
///
/// - [`Error::WrongType`]: the key exists but stores a different structure type
/// - [`Error::NotFound`]: an operation requires a key/element to exist
/// - [`Error::InvalidArgument`]: invalid input such as out-of-range indices
/// - [`Error::Encode`] / [`Error::Decode`]: codec failures when converting values
///
/// # Example
///
/// ```rust
/// use heaplet::{Error, Store};
///
/// let store = Store::new();
///
/// // Create a hash under "k".
/// store.hash("k").hset("f", &1_i64).unwrap();
///
/// // Now try to use "k" as a KV/String key => WrongType.
/// let err = store.kv().get::<i64>("k").unwrap_err();
///
/// match err {
///     Error::WrongType { expected, got } => {
///         assert_eq!(expected, "string");
///         assert_eq!(got, "hash");
///     }
///     other => panic!("unexpected error: {other}"),
/// }
/// ```
#[derive(Debug)]
pub enum Error {
    /// The requested key or element was not found.
    NotFound,

    /// The caller provided an invalid argument (e.g. out-of-range index).
    InvalidArgument(String),

    /// The operation was attempted on a key holding a different value type.
    WrongType {
        /// Expected value type.
        expected: &'static str,
        /// Actual value type stored under the key.
        got: &'static str,
    },

    /// Encoding failed.
    Encode(String),

    /// Decoding failed.
    Decode(String),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::NotFound => write!(f, "not found"),
            Error::InvalidArgument(s) => write!(f, "invalid argument: {s}"),
            Error::WrongType { expected, got } => {
                write!(f, "wrong type: expected {expected}, got {got}")
            }
            Error::Encode(e) => write!(f, "encode error: {e}"),
            Error::Decode(e) => write!(f, "decode error: {e}"),
        }
    }
}

impl std::error::Error for Error {}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn error_debug_smoke() {
        let e = Error::Decode("x".into());
        let _ = format!("{e:?}");
    }

    #[test]
    fn error_display_smoke() {
        let e = Error::WrongType {
            expected: "string",
            got: "hash",
        };
        let s = e.to_string();
        assert!(s.contains("expected string"));
        assert!(s.contains("got hash"));
    }
}