#[derive(Debug, thiserror::Error)]
pub enum StegoError {
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("image error: {0}")]
Image(#[from] image::ImageError),
#[error("invalid configuration: {0}")]
InvalidConfig(String),
#[error("invalid header (corrupt or not a StegoRust image)")]
InvalidHeader,
#[error("authentication failed (wrong password or tampered image)")]
AuthenticationFailed,
#[error("integrity check failed: reassembled payload hash mismatch")]
IntegrityCheckFailed,
#[error("insufficient capacity: need {needed} bytes, available {available}")]
InsufficientCapacity {
needed: usize,
available: usize,
},
#[error("missing chunks: found {found}, expected {expected}")]
MissingChunks {
found: usize,
expected: usize,
},
#[error("duplicate chunk index {0}")]
DuplicateChunk(u8),
#[error("multiple message_ids in the provided image set")]
MixedMessages,
#[error("bits_per_channel must be 1..=8, got {0}")]
InvalidBitsPerChannel(u8),
#[error("KDF error: {0}")]
Kdf(String),
#[error("cipher error: {0}")]
Cipher(String),
}
pub type Result<T> = std::result::Result<T, StegoError>;
#[cfg(test)]
mod tests {
use super::*;
use std::error::Error;
#[test]
fn error_variants_display_non_empty() {
let variants: Vec<Box<dyn Error>> = vec![
Box::new(StegoError::InvalidHeader),
Box::new(StegoError::AuthenticationFailed),
Box::new(StegoError::IntegrityCheckFailed),
Box::new(StegoError::InsufficientCapacity {
needed: 10,
available: 5,
}),
Box::new(StegoError::MissingChunks {
found: 1,
expected: 3,
}),
Box::new(StegoError::DuplicateChunk(2)),
Box::new(StegoError::MixedMessages),
Box::new(StegoError::InvalidBitsPerChannel(9)),
Box::new(StegoError::Kdf("test".into())),
Box::new(StegoError::Cipher("test".into())),
Box::new(StegoError::InvalidConfig("test".into())),
];
for e in variants {
assert!(!e.to_string().is_empty(), "empty Display for {e:?}");
}
}
}