use std::{
iter::Sum,
ops::{Add, AddAssign, Div, Mul},
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize, Hash)]
pub struct SemanticLength(pub u32);
impl SemanticLength {
pub fn to_usize(self) -> usize {
assert_usize(self.0)
}
}
impl Add<SemanticLength> for SemanticLength {
type Output = SemanticLength;
fn add(self, rhs: SemanticLength) -> Self::Output {
SemanticLength(self.0 + rhs.0)
}
}
impl AddAssign for SemanticLength {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}
impl Mul<ElementTypesLength> for SemanticLength {
type Output = SemiFlattenedLength;
fn mul(self, rhs: ElementTypesLength) -> Self::Output {
SemiFlattenedLength(self.0 * rhs.0)
}
}
impl std::fmt::Display for SemanticLength {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize, Hash)]
pub struct ElementTypesLength(pub u32);
impl ElementTypesLength {
pub fn to_usize(self) -> usize {
assert_usize(self.0)
}
}
impl Mul<SemanticLength> for ElementTypesLength {
type Output = SemiFlattenedLength;
fn mul(self, rhs: SemanticLength) -> Self::Output {
SemiFlattenedLength(self.0 * rhs.0)
}
}
impl Mul<ElementsFlattenedLength> for SemanticLength {
type Output = FlattenedLength;
fn mul(self, rhs: ElementsFlattenedLength) -> Self::Output {
FlattenedLength(self.0 * rhs.0)
}
}
impl std::fmt::Display for ElementTypesLength {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize, Hash)]
#[cfg_attr(feature = "arb", derive(proptest_derive::Arbitrary))]
pub struct SemiFlattenedLength(pub u32);
impl SemiFlattenedLength {
pub fn to_usize(self) -> usize {
assert_usize(self.0)
}
}
impl std::fmt::Display for SemiFlattenedLength {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Div<ElementTypesLength> for SemiFlattenedLength {
type Output = SemanticLength;
fn div(self, rhs: ElementTypesLength) -> Self::Output {
if self.0 % rhs.0 != 0 {
panic!(
"Division of SemiFlattenedLength {} by ElementTypesLength {} has remainder",
self.0, rhs.0
);
}
SemanticLength(self.0 / rhs.0)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize, Hash)]
pub struct ElementsFlattenedLength(pub u32);
impl ElementsFlattenedLength {
pub fn to_usize(self) -> usize {
assert_usize(self.0)
}
}
impl std::fmt::Display for ElementsFlattenedLength {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Mul<SemanticLength> for ElementsFlattenedLength {
type Output = FlattenedLength;
fn mul(self, rhs: SemanticLength) -> Self::Output {
FlattenedLength(self.0 * rhs.0)
}
}
impl From<FlattenedLength> for ElementsFlattenedLength {
fn from(flattened_length: FlattenedLength) -> Self {
Self(flattened_length.0)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize, Hash)]
pub struct FlattenedLength(pub u32);
impl FlattenedLength {
pub fn to_usize(self) -> usize {
assert_usize(self.0)
}
}
impl std::fmt::Display for FlattenedLength {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Add for FlattenedLength {
type Output = FlattenedLength;
fn add(self, rhs: Self) -> Self::Output {
FlattenedLength(self.0 + rhs.0)
}
}
impl AddAssign for FlattenedLength {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}
impl Sum for FlattenedLength {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(FlattenedLength(0), |acc, x| acc + x)
}
}
impl Div<ElementsFlattenedLength> for FlattenedLength {
type Output = SemanticLength;
fn div(self, rhs: ElementsFlattenedLength) -> Self::Output {
if self.0 % rhs.0 != 0 {
panic!(
"Division of FlattenedLength {} by ElementsFlattenedLength {} has remainder",
self.0, rhs.0
);
}
SemanticLength(self.0 / rhs.0)
}
}
fn assert_usize(value: u32) -> usize {
value.try_into().expect("Failed conversion from u32 to usize")
}