use std::slice::ChunksExact;
use image::RgbImage;
use super::{SteganographyError, lsb};
const MIN_CARRIER_CAPACITY: usize = 27;
pub struct Carrier(RgbImage);
impl Carrier {
pub fn new(rgb_image: RgbImage) -> Result<Self, SteganographyError> {
if rgb_image.len() >= MIN_CARRIER_CAPACITY {
Ok(Self(rgb_image))
} else {
Err(SteganographyError::SmallCarrier)
}
}
pub fn capacity(&self) -> usize {
self.0.len()
}
pub fn subpixels(&mut self) -> impl ExactSizeIterator<Item = &mut u8> {
self.0.iter_mut()
}
pub fn payload_chunks(&self) -> ChunksExact<'_, u8> {
self.0.chunks_exact(lsb::BITS_PER_BYTE)
}
pub fn unwrap(self) -> RgbImage {
self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
const CHUNKS_IN_MIN_CAPACITY_CARRIER: usize = 3;
#[test]
fn create_new_carrier() {
let rgb_image = RgbImage::new(3, 3);
let result = Carrier::new(rgb_image);
assert!(result.is_ok());
}
#[test]
fn try_to_create_new_carrier() {
let rgb_image = RgbImage::new(3, 2);
let result = Carrier::new(rgb_image);
assert!(result.is_err());
let error = result.err().unwrap();
assert!(matches!(error, SteganographyError::SmallCarrier));
}
#[test]
fn verify_capacity() {
let rgb_image = RgbImage::new(3, 3);
let result = Carrier::new(rgb_image);
assert!(result.is_ok());
let result = result.unwrap();
assert_eq!(result.capacity(), MIN_CARRIER_CAPACITY);
}
#[test]
fn verify_chunks_size() {
let rgb_image = RgbImage::new(3, 3);
let result = Carrier::new(rgb_image);
assert!(result.is_ok());
let result = result.unwrap();
assert_eq!(
result.payload_chunks().len(),
CHUNKS_IN_MIN_CAPACITY_CARRIER
);
}
}