use std::{marker::PhantomData, num::NonZeroUsize};
#[derive(Debug)]
pub(super) struct Elements<T> {
elements: usize,
_type: PhantomData<T>,
}
impl<T> Clone for Elements<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for Elements<T> {}
impl<T> Elements<T> {
pub(super) const fn new(elements: usize) -> Self {
Self {
elements,
_type: PhantomData,
}
}
pub(super) const fn value(self) -> usize {
self.elements
}
pub(super) const fn cast<U>(self) -> Elements<U> {
Elements::new(self.value())
}
pub(super) const fn bytes(self) -> Bytes {
Bytes::new(self.elements * std::mem::size_of::<T>())
}
}
impl<T, U> PartialEq<Elements<U>> for Elements<T> {
fn eq(&self, other: &Elements<U>) -> bool {
self.value() == other.value()
}
}
impl<T> std::ops::Mul<usize> for Elements<T> {
type Output = Self;
fn mul(self, by: usize) -> Self {
Self::new(self.value() * by)
}
}
impl<T> std::ops::Add for Elements<T> {
type Output = Self;
fn add(self, by: Elements<T>) -> Self {
Self::new(self.value() + by.value())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub(super) struct Bytes(usize);
impl Bytes {
pub(super) const fn new(bytes: usize) -> Self {
Self(bytes)
}
pub(super) const fn value(self) -> usize {
self.0
}
}
pub(super) const fn value_or_one(x: usize) -> NonZeroUsize {
match NonZeroUsize::new(x) {
Some(value) => value,
None => NonZeroUsize::MIN,
}
}
macro_rules! newtype {
($(#[$doc:meta])* $vis:vis $name:ident) => {
$(#[$doc])*
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
$vis struct $name(NonZeroUsize);
impl $name {
pub(crate) const fn new(value: NonZeroUsize) -> Self {
Self(value)
}
pub(crate) const fn value(self) -> NonZeroUsize {
self.0
}
}
}
}
newtype! {
pub(crate) DimK
}
#[cfg(test)]
impl DimK {
pub(super) fn from_bound(bound: super::bounds::Bound) -> Self {
Self::new(NonZeroUsize::new(bound.value()).unwrap())
}
}