#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error("invalid configuration: {reason}. Fix: {fix}")]
InvalidConfig {
reason: String,
fix: String,
},
#[error("document too large: size={size}, max={max}. Fix: increase max_document_size in Config or filter large documents before deduplication.")]
DocumentTooLarge {
size: usize,
max: usize,
},
#[error("empty document at index {index}. Fix: filter empty documents before deduplication.")]
EmptyDocument {
index: usize,
},
#[error("hashing failed: {reason}. Fix: check for integer overflow or memory exhaustion.")]
HashingFailed {
reason: String,
},
#[error("memory limit exceeded: {usage_bytes} bytes. Fix: increase memory_limit_in_mb in Config or reduce num_bands.")]
MemoryLimitExceeded {
usage_bytes: u64,
},
#[error("io error: {0}. Fix: check file permissions and disk space.")]
Io(#[from] std::io::Error),
}
pub type Result<T> = std::result::Result<T, Error>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_display_includes_fix() {
let err = Error::InvalidConfig {
reason: "num_bands must divide signature_size".to_string(),
fix: "use a signature_size divisible by num_bands".to_string(),
};
let msg = err.to_string();
assert!(msg.contains("Fix:"));
assert!(msg.contains("signature_size"));
}
#[test]
fn document_too_large_error_includes_size() {
let err = Error::DocumentTooLarge {
size: 1000000,
max: 100000,
};
let msg = err.to_string();
assert!(msg.contains("1000000"));
assert!(msg.contains("100000"));
}
}