use super::{
DimensionOverflow, GeometryOverflow, InsufficientPlane, InsufficientStride, ZeroDimension,
};
use derive_more::{IsVariant, TryUnwrap, Unwrap};
use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum GbrFloatFrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
DimensionOverflow(DimensionOverflow),
#[error(transparent)]
InsufficientPlane(InsufficientPlane),
#[error(transparent)]
StrideBelowWidth(InsufficientStride),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}
#[inline(always)]
const fn check_dims(width: u32, height: u32) -> Result<(usize, usize), GbrFloatFrameError> {
if width == 0 || height == 0 {
return Err(GbrFloatFrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
if (width as i64) * (height as i64) > i32::MAX as i64 {
return Err(GbrFloatFrameError::DimensionOverflow(
DimensionOverflow::new(width, height),
));
}
Ok((width as usize, height as usize))
}
#[inline(always)]
const fn check_plane(
name: &'static str,
plane_len: usize,
stride: u32,
w: usize,
h: usize,
height: u32,
) -> Result<(), GbrFloatFrameError> {
let _ = name;
if (stride as usize) < w {
return Err(GbrFloatFrameError::StrideBelowWidth(
InsufficientStride::new(stride, w as u32),
));
}
let stride_times_hm1 = match (stride as usize).checked_mul(h - 1) {
Some(v) => v,
None => {
return Err(GbrFloatFrameError::GeometryOverflow(GeometryOverflow::new(
stride, height,
)));
}
};
let needed = match stride_times_hm1.checked_add(w) {
Some(v) => v,
None => {
return Err(GbrFloatFrameError::GeometryOverflow(GeometryOverflow::new(
stride, height,
)));
}
};
if plane_len < needed {
return Err(GbrFloatFrameError::InsufficientPlane(
InsufficientPlane::new(needed, plane_len),
));
}
Ok(())
}
#[derive(Debug, Clone, Copy)]
pub struct Gbrpf32Frame<'a, const BE: bool = false> {
g: &'a [f32],
b: &'a [f32],
r: &'a [f32],
width: u32,
height: u32,
g_stride: u32,
b_stride: u32,
r_stride: u32,
}
pub type Gbrpf32LeFrame<'a> = Gbrpf32Frame<'a, false>;
pub type Gbrpf32BeFrame<'a> = Gbrpf32Frame<'a, true>;
impl<'a, const BE: bool> Gbrpf32Frame<'a, BE> {
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub const fn try_new(
g: &'a [f32],
b: &'a [f32],
r: &'a [f32],
width: u32,
height: u32,
g_stride: u32,
b_stride: u32,
r_stride: u32,
) -> Result<Self, GbrFloatFrameError> {
let (w, h) = match check_dims(width, height) {
Ok(v) => v,
Err(e) => return Err(e),
};
if let Err(e) = check_plane("g", g.len(), g_stride, w, h, height) {
return Err(e);
}
if let Err(e) = check_plane("b", b.len(), b_stride, w, h, height) {
return Err(e);
}
if let Err(e) = check_plane("r", r.len(), r_stride, w, h, height) {
return Err(e);
}
Ok(Self {
g,
b,
r,
width,
height,
g_stride,
b_stride,
r_stride,
})
}
#[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 g(&self) -> &'a [f32] {
self.g
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn g_stride(&self) -> u32 {
self.g_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn b(&self) -> &'a [f32] {
self.b
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn b_stride(&self) -> u32 {
self.b_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn r(&self) -> &'a [f32] {
self.r
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn r_stride(&self) -> u32 {
self.r_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_be(&self) -> bool {
BE
}
}
#[derive(Debug, Clone, Copy)]
pub struct Gbrapf32Frame<'a, const BE: bool = false> {
g: &'a [f32],
b: &'a [f32],
r: &'a [f32],
a: &'a [f32],
width: u32,
height: u32,
g_stride: u32,
b_stride: u32,
r_stride: u32,
a_stride: u32,
}
pub type Gbrapf32LeFrame<'a> = Gbrapf32Frame<'a, false>;
pub type Gbrapf32BeFrame<'a> = Gbrapf32Frame<'a, true>;
impl<'a, const BE: bool> Gbrapf32Frame<'a, BE> {
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub const fn try_new(
g: &'a [f32],
b: &'a [f32],
r: &'a [f32],
a: &'a [f32],
width: u32,
height: u32,
g_stride: u32,
b_stride: u32,
r_stride: u32,
a_stride: u32,
) -> Result<Self, GbrFloatFrameError> {
let (w, h) = match check_dims(width, height) {
Ok(v) => v,
Err(e) => return Err(e),
};
if let Err(e) = check_plane("g", g.len(), g_stride, w, h, height) {
return Err(e);
}
if let Err(e) = check_plane("b", b.len(), b_stride, w, h, height) {
return Err(e);
}
if let Err(e) = check_plane("r", r.len(), r_stride, w, h, height) {
return Err(e);
}
if let Err(e) = check_plane("a", a.len(), a_stride, w, h, height) {
return Err(e);
}
Ok(Self {
g,
b,
r,
a,
width,
height,
g_stride,
b_stride,
r_stride,
a_stride,
})
}
#[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 g(&self) -> &'a [f32] {
self.g
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn g_stride(&self) -> u32 {
self.g_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn b(&self) -> &'a [f32] {
self.b
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn b_stride(&self) -> u32 {
self.b_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn r(&self) -> &'a [f32] {
self.r
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn r_stride(&self) -> u32 {
self.r_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn a(&self) -> &'a [f32] {
self.a
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn a_stride(&self) -> u32 {
self.a_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_be(&self) -> bool {
BE
}
}
#[derive(Debug, Clone, Copy)]
pub struct Gbrpf16Frame<'a, const BE: bool = false> {
g: &'a [half::f16],
b: &'a [half::f16],
r: &'a [half::f16],
width: u32,
height: u32,
g_stride: u32,
b_stride: u32,
r_stride: u32,
}
pub type Gbrpf16LeFrame<'a> = Gbrpf16Frame<'a, false>;
pub type Gbrpf16BeFrame<'a> = Gbrpf16Frame<'a, true>;
impl<'a, const BE: bool> Gbrpf16Frame<'a, BE> {
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub const fn try_new(
g: &'a [half::f16],
b: &'a [half::f16],
r: &'a [half::f16],
width: u32,
height: u32,
g_stride: u32,
b_stride: u32,
r_stride: u32,
) -> Result<Self, GbrFloatFrameError> {
let (w, h) = match check_dims(width, height) {
Ok(v) => v,
Err(e) => return Err(e),
};
if let Err(e) = check_plane("g", g.len(), g_stride, w, h, height) {
return Err(e);
}
if let Err(e) = check_plane("b", b.len(), b_stride, w, h, height) {
return Err(e);
}
if let Err(e) = check_plane("r", r.len(), r_stride, w, h, height) {
return Err(e);
}
Ok(Self {
g,
b,
r,
width,
height,
g_stride,
b_stride,
r_stride,
})
}
#[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 g(&self) -> &'a [half::f16] {
self.g
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn g_stride(&self) -> u32 {
self.g_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn b(&self) -> &'a [half::f16] {
self.b
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn b_stride(&self) -> u32 {
self.b_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn r(&self) -> &'a [half::f16] {
self.r
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn r_stride(&self) -> u32 {
self.r_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_be(&self) -> bool {
BE
}
}
#[derive(Debug, Clone, Copy)]
pub struct Gbrapf16Frame<'a, const BE: bool = false> {
g: &'a [half::f16],
b: &'a [half::f16],
r: &'a [half::f16],
a: &'a [half::f16],
width: u32,
height: u32,
g_stride: u32,
b_stride: u32,
r_stride: u32,
a_stride: u32,
}
pub type Gbrapf16LeFrame<'a> = Gbrapf16Frame<'a, false>;
pub type Gbrapf16BeFrame<'a> = Gbrapf16Frame<'a, true>;
impl<'a, const BE: bool> Gbrapf16Frame<'a, BE> {
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub const fn try_new(
g: &'a [half::f16],
b: &'a [half::f16],
r: &'a [half::f16],
a: &'a [half::f16],
width: u32,
height: u32,
g_stride: u32,
b_stride: u32,
r_stride: u32,
a_stride: u32,
) -> Result<Self, GbrFloatFrameError> {
let (w, h) = match check_dims(width, height) {
Ok(v) => v,
Err(e) => return Err(e),
};
if let Err(e) = check_plane("g", g.len(), g_stride, w, h, height) {
return Err(e);
}
if let Err(e) = check_plane("b", b.len(), b_stride, w, h, height) {
return Err(e);
}
if let Err(e) = check_plane("r", r.len(), r_stride, w, h, height) {
return Err(e);
}
if let Err(e) = check_plane("a", a.len(), a_stride, w, h, height) {
return Err(e);
}
Ok(Self {
g,
b,
r,
a,
width,
height,
g_stride,
b_stride,
r_stride,
a_stride,
})
}
#[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 g(&self) -> &'a [half::f16] {
self.g
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn g_stride(&self) -> u32 {
self.g_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn b(&self) -> &'a [half::f16] {
self.b
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn b_stride(&self) -> u32 {
self.b_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn r(&self) -> &'a [half::f16] {
self.r
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn r_stride(&self) -> u32 {
self.r_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn a(&self) -> &'a [half::f16] {
self.a
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn a_stride(&self) -> u32 {
self.a_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_be(&self) -> bool {
BE
}
}