tegdb 0.5.0

The name TegridyDB (short for TegDB) is inspired by the Tegridy Farm in South Park and tries to correct some of the wrong database implementations, such as null support, implicit conversion support, etc.
Documentation
use std::fmt;
use std::io;

/// Custom error type for tegdb operations
#[derive(Debug)]
pub enum Error {
    /// I/O error from underlying file operations
    Io(io::Error),
    /// Error when key is too large (> 1KB)
    KeyTooLarge(usize),
    /// Error when value is too large (> 256KB)
    ValueTooLarge(usize),
    /// Error when database file is locked by another process
    FileLocked(String),
    /// Error when file is corrupted
    Corrupted(String),
    /// Storage file does not have the expected magic header
    InvalidMagic,
    /// Storage file format version is unsupported
    UnsupportedVersion(u16),
    /// Storage file header is malformed
    CorruptHeader(&'static str),
    /// SQL parsing, planning, or execution error
    SqlError(String),
    /// Error during SQL parsing
    ParseError(String),
    /// Error during query planning
    PlanError(String),
    /// Table not found
    TableNotFound(String),
    /// Column not found
    ColumnNotFound(String),
    /// Exceeded configured in-memory quota (too many keys)
    OutOfMemoryQuota { max_keys: usize },
    /// Exceeded configured on-disk quota (log file would exceed limit)
    OutOfStorageQuota { bytes: u64 },
    /// Other database errors
    Other(String),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::Io(err) => write!(f, "I/O error: {err}"),
            Error::KeyTooLarge(size) => write!(f, "Key too large: {size} bytes (max 1KB)"),
            Error::ValueTooLarge(size) => write!(f, "Value too large: {size} bytes (max 256KB)"),
            Error::FileLocked(msg) => write!(f, "Database file is locked: {msg}"),
            Error::Corrupted(msg) => write!(f, "Database corrupted: {msg}"),
            Error::InvalidMagic => write!(f, "Invalid storage file magic header"),
            Error::UnsupportedVersion(v) => write!(f, "Unsupported storage file version: {v}"),
            Error::CorruptHeader(msg) => write!(f, "Corrupt storage header: {msg}"),
            Error::SqlError(msg) => write!(f, "SQL error: {msg}"),
            Error::ParseError(msg) => write!(f, "SQL parse error: {msg}"),
            Error::PlanError(msg) => write!(f, "Query planning error: {msg}"),
            Error::TableNotFound(table) => write!(f, "Table '{table}' not found"),
            Error::ColumnNotFound(column) => write!(f, "Column '{column}' not found"),
            Error::OutOfMemoryQuota { max_keys } => {
                write!(f, "In-memory quota exceeded (max {max_keys} keys)")
            }
            Error::OutOfStorageQuota { bytes } => {
                write!(f, "Storage quota exceeded (max {bytes} bytes)")
            }
            Error::Other(msg) => write!(f, "Database error: {msg}"),
        }
    }
}

impl std::error::Error for Error {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Error::Io(err) => Some(err),
            _ => None,
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::Io(err)
    }
}

impl From<serde_json::Error> for Error {
    fn from(err: serde_json::Error) -> Self {
        Error::Other(format!("JSON parsing error: {}", err))
    }
}

/// Result type for tegdb operations
pub type Result<T> = std::result::Result<T, Error>;