use crate::mode::{Builder, SampleDepth};
use std::num::NonZero;
#[derive(Debug)]
#[derive_const(Clone)]
pub struct Mode {
sample_depth: SampleDepth,
channel_count: NonZero<u8>,
width: NonZero<u16>,
height: NonZero<u16>,
duration: u64,
}
impl Mode {
const MAX_CHANNEL_COUNT: u32 = 2_u32.pow(u8::BITS - 1);
const MAX_WIDTH: u32 = 2_u32.pow(u16::BITS - 1);
#[must_use]
pub const fn from_builder(builder: Builder) -> Self {
let sample_depth = builder.sample_depth
.expect("expected sampling depth");
let sample_depth = SampleDepth::new(sample_depth)
.expect("sampling depth must be non-zero and at most `8`");
let channel_count = builder.channel_count
.expect("expected channel count");
let channel_count = match channel_count {
1..Self::MAX_CHANNEL_COUNT => {
NonZero::<u8>::new(channel_count.truncate()).unwrap()
}
_ => {
panic!("channel count must be non-zero and at most `128`");
}
};
let width = builder.width
.expect("expected frame width");
let width = match width {
1..Self::MAX_WIDTH => {
NonZero::<u16>::new(width.truncate()).unwrap()
}
_ => {
panic!("frame width must be non-zero and at most `32768`");
}
};
let height = builder.height
.expect("expected frame height");
let height = match height {
1..Self::MAX_WIDTH => {
NonZero::<u16>::new(height.truncate()).unwrap()
}
_ => {
panic!("frame height must be non-zero and at most `32768`");
}
};
let duration = builder.duration
.expect("expected render duration");
let render_size = u128::from(sample_depth.get())
.wrapping_mul(channel_count.get().into())
.wrapping_mul(width.get().into())
.wrapping_mul(height.get().into())
.wrapping_mul(duration.into());
cfg_select! {
target_pointer_width = "16" => {
assert!(
isize::try_from(render_size).is_ok(),
"render size may not be greater than `32767`",
);
}
target_pointer_width = "32" => {
assert!(
isize::try_from(render_size).is_ok(),
"render size may not be greater than `2147483647`",
);
}
target_pointer_width = "64" => {
assert!(
isize::try_from(render_size).is_ok(),
"render size may not be greater than `9223372036854775807`",
);
}
_ => {
assert!(
isize::try_from(render_size).is_ok(),
"render size may not be greater than `isize::MAX`",
);
}
}
Self { sample_depth, channel_count, width, height, duration }
}
#[inline]
#[must_use]
pub const fn sample_count(&self) -> u64 {
u64::from(self.channel_count().get())
.wrapping_mul(self.width().get().into())
.wrapping_mul(self.height().get().into())
.wrapping_mul(self.duration)
}
#[inline(always)]
#[must_use]
pub const fn sample_depth(&self) -> SampleDepth {
self.sample_depth
}
#[inline]
#[must_use]
pub const fn channel_count(&self) -> NonZero<u32> {
self.channel_count.into()
}
#[inline]
#[must_use]
pub const fn width(&self) -> NonZero<u32> {
self.width.into()
}
#[inline]
#[must_use]
pub const fn height(&self) -> NonZero<u32> {
self.height.into()
}
#[inline(always)]
#[must_use]
pub const fn duration(&self) -> u64 {
self.duration
}
#[inline]
#[must_use]
pub const fn frame_stride(&self) -> u64 {
u64::from(self.channel_count().get())
.wrapping_mul(self.width().get().into())
.wrapping_mul(self.height().get().into())
}
}