use crate::types::{NodeId, TxId};
use std::borrow::Cow;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum KiteError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Invalid magic number: expected 0x{expected:08X}, got 0x{got:08X}")]
InvalidMagic { expected: u32, got: u32 },
#[error("Version mismatch: file requires version {required}, we support {current}")]
VersionMismatch { required: u32, current: u32 },
#[error("CRC mismatch: stored 0x{stored:08X}, computed 0x{computed:08X}")]
CrcMismatch { stored: u32, computed: u32 },
#[error("Node not found: {0}")]
NodeNotFound(NodeId),
#[error("Key not found: {0}")]
KeyNotFound(String),
#[error("Duplicate key: {0}")]
DuplicateKey(String),
#[error("Transaction {txid} conflict on keys: {keys:?}")]
Conflict { txid: TxId, keys: Vec<String> },
#[error("WAL buffer full: checkpoint required before continuing writes")]
WalBufferFull,
#[error("Database is read-only")]
ReadOnly,
#[error("Invalid snapshot: {0}")]
InvalidSnapshot(String),
#[error("Invalid WAL: {0}")]
InvalidWal(String),
#[error("Compression error: {0}")]
Compression(String),
#[error("No active transaction")]
NoTransaction,
#[error("Transaction already in progress")]
TransactionInProgress,
#[error("Database is closed")]
DatabaseClosed,
#[error("Failed to acquire lock: {0}")]
LockFailed(String),
#[error("Invalid section ID: {0}")]
InvalidSection(u32),
#[error("Invalid property value tag: {0}")]
InvalidPropTag(u8),
#[error("Invalid WAL record type: {0}")]
InvalidWalRecordType(u8),
#[error("Vector dimension mismatch: expected {expected}, got {got}")]
VectorDimensionMismatch { expected: usize, got: usize },
#[error("Invalid database path: {0}")]
InvalidPath(String),
#[error("Failed to create database: {0}")]
CreateFailed(String),
#[error("Serialization error: {0}")]
Serialization(String),
#[error("Internal error: {0}")]
Internal(String),
#[error("Invalid schema: {0}")]
InvalidSchema(Cow<'static, str>),
#[error("Invalid query: {0}")]
InvalidQuery(Cow<'static, str>),
}
pub type Result<T> = std::result::Result<T, KiteError>;
impl KiteError {
pub fn conflict(txid: TxId, keys: Vec<String>) -> Self {
KiteError::Conflict { txid, keys }
}
pub fn is_conflict(&self) -> bool {
matches!(self, KiteError::Conflict { .. })
}
pub fn conflict_keys(&self) -> Option<&[String]> {
match self {
KiteError::Conflict { keys, .. } => Some(keys),
_ => None,
}
}
}
impl From<serde_json::Error> for KiteError {
fn from(err: serde_json::Error) -> Self {
KiteError::Serialization(err.to_string())
}
}