use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub enum KvError {
InvalidDimensions {
expected: usize,
actual: usize,
operation: String,
},
CapacityExceeded {
requested: usize,
capacity: usize,
},
InvalidCacheState(String),
EmptyCache(String),
InvalidTokenSequence {
reason: String,
position: Option<usize>,
},
QuantizationError(String),
LayerOutOfBounds {
index: usize,
total_layers: usize,
},
PositionOutOfBounds {
index: usize,
total_positions: usize,
},
MixedPrecisionError(String),
}
impl fmt::Display for KvError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
KvError::InvalidDimensions { expected, actual, operation } => {
write!(f, "Invalid dimensions for '{}': expected {}, got {}",
operation, expected, actual)
}
KvError::CapacityExceeded { requested, capacity } => {
write!(f, "Cache capacity exceeded: requested {}, capacity {}",
requested, capacity)
}
KvError::InvalidCacheState(msg) => {
write!(f, "Invalid cache state: {}", msg)
}
KvError::EmptyCache(operation) => {
write!(f, "Cannot perform '{}' on empty cache", operation)
}
KvError::InvalidTokenSequence { reason, position } => {
if let Some(pos) = position {
write!(f, "Invalid token sequence at position {}: {}", pos, reason)
} else {
write!(f, "Invalid token sequence: {}", reason)
}
}
KvError::QuantizationError(msg) => {
write!(f, "Quantization error: {}", msg)
}
KvError::LayerOutOfBounds { index, total_layers } => {
write!(f, "Layer index {} out of bounds (total layers: {})",
index, total_layers)
}
KvError::PositionOutOfBounds { index, total_positions } => {
write!(f, "Position index {} out of bounds (total positions: {})",
index, total_positions)
}
KvError::MixedPrecisionError(msg) => {
write!(f, "Mixed precision operation error: {}", msg)
}
}
}
}
impl std::error::Error for KvError {}
impl From<CacheValidationError> for KvError {
fn from(err: CacheValidationError) -> Self {
match err {
CacheValidationError::EmptySequence => {
KvError::InvalidTokenSequence {
reason: "Empty token sequence".to_string(),
position: None,
}
}
CacheValidationError::SequenceTooLong { length, max_length } => {
KvError::InvalidTokenSequence {
reason: format!("Sequence too long: {} (max {})", length, max_length),
position: None,
}
}
CacheValidationError::InvalidTokenId { token_id, position } => {
KvError::InvalidTokenSequence {
reason: format!("Invalid token ID {}", token_id),
position: Some(position),
}
}
CacheValidationError::DimensionMismatch { layer, expected, actual } => {
KvError::InvalidDimensions {
expected,
actual,
operation: format!("layer {} KV cache", layer),
}
}
}
}
}
pub type KvResult<T> = Result<T, KvError>;
#[derive(Debug, Clone, PartialEq)]
pub enum CacheValidationError {
EmptySequence,
SequenceTooLong {
length: usize,
max_length: usize,
},
InvalidTokenId {
token_id: u32,
position: usize,
},
DimensionMismatch {
layer: usize,
expected: usize,
actual: usize,
},
}
impl fmt::Display for CacheValidationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CacheValidationError::EmptySequence => {
write!(f, "Token sequence cannot be empty")
}
CacheValidationError::SequenceTooLong { length, max_length } => {
write!(f, "Token sequence too long: {} (max {})", length, max_length)
}
CacheValidationError::InvalidTokenId { token_id, position } => {
write!(f, "Invalid token ID {} at position {}", token_id, position)
}
CacheValidationError::DimensionMismatch { layer, expected, actual } => {
write!(f, "Dimension mismatch in layer {}: expected {}, got {}",
layer, expected, actual)
}
}
}
}
impl std::error::Error for CacheValidationError {}
pub type ValidationResult<T> = Result<T, CacheValidationError>;
#[derive(Debug, Clone)]
pub struct KvContext {
pub operation: String,
pub layer: Option<usize>,
pub position: Option<usize>,
pub sequence_length: Option<usize>,
}
impl KvContext {
pub fn new(operation: impl Into<String>) -> Self {
Self {
operation: operation.into(),
layer: None,
position: None,
sequence_length: None,
}
}
pub fn with_layer(mut self, layer: usize) -> Self {
self.layer = Some(layer);
self
}
pub fn with_position(mut self, position: usize) -> Self {
self.position = Some(position);
self
}
pub fn with_sequence_length(mut self, length: usize) -> Self {
self.sequence_length = Some(length);
self
}
pub fn dimension_error(&self, expected: usize, actual: usize) -> KvError {
KvError::InvalidDimensions {
expected,
actual,
operation: self.operation.clone(),
}
}
pub fn out_of_bounds_error(&self, index: usize, total: usize, is_layer: bool) -> KvError {
if is_layer {
KvError::LayerOutOfBounds { index, total_layers: total }
} else {
KvError::PositionOutOfBounds { index, total_positions: total }
}
}
}