use super::{GeometryOverflow, InsufficientPlane, InsufficientStride, ZeroDimension};
use derive_more::{IsVariant, TryUnwrap, Unwrap};
use thiserror::Error;
#[derive(Debug, Clone, Copy)]
pub struct MonoFrame<'a, const INVERT: bool> {
data: &'a [u8],
width: u32,
height: u32,
stride: u32, }
impl<'a, const INVERT: bool> MonoFrame<'a, INVERT> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
data: &'a [u8],
width: u32,
height: u32,
stride: u32,
) -> Result<Self, MonoFrameError> {
if width == 0 || height == 0 {
return Err(MonoFrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
let min_stride = width.div_ceil(8);
if stride < min_stride {
return Err(MonoFrameError::InsufficientStride(InsufficientStride::new(
stride, min_stride,
)));
}
let data_min = match (stride as usize).checked_mul(height as usize) {
Some(v) => v,
None => {
return Err(MonoFrameError::GeometryOverflow(GeometryOverflow::new(
stride, height,
)));
}
};
if data.len() < data_min {
return Err(MonoFrameError::InsufficientDataPlane(
InsufficientPlane::new(data_min, data.len()),
));
}
Ok(Self {
data,
width,
height,
stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(data: &'a [u8], width: u32, height: u32, stride: u32) -> Self {
match Self::try_new(data, width, height, stride) {
Ok(frame) => frame,
Err(_) => panic!("invalid MonoFrame dimensions or plane length"),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn data(&self) -> &'a [u8] {
self.data
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn width(&self) -> u32 {
self.width
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn height(&self) -> u32 {
self.height
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn stride(&self) -> u32 {
self.stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y(&self) -> &'a [u8] {
self.data
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y_stride(&self) -> u32 {
self.stride
}
}
pub type MonoblackFrame<'a> = MonoFrame<'a, false>;
pub type MonowhiteFrame<'a> = MonoFrame<'a, true>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum MonoFrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
InsufficientStride(InsufficientStride),
#[error(transparent)]
InsufficientDataPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}