#![deny(rustdoc::broken_intra_doc_links)]
use derive_more::{AsRef, Display};
use duplicate::duplicate_item;
use into_inner::IntoInner;
use num_valid::{RealScalar, core::errors::capture_backtrace, kernels::RawScalarTrait};
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use std::{
backtrace::Backtrace,
hash::{Hash, Hasher},
};
use thiserror::Error;
use try_create::TryNew;
pub trait PositiveIntTrait:
AsRef<usize>
+ From<PositiveSize>
+ Into<PositiveSize>
+ TryFrom<Size>
+ IntoInner<InnerType = usize>
+ TryNew<Error = ErrorsPositiveInt>
+ Copy
+ Clone
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Hash
+ std::fmt::Debug
+ std::fmt::Display
+ Serialize
+ DeserializeOwned
+ Sync
+ Send
{
}
#[duplicate_item(
In Out;
[NumIntervals] [PositiveSize];
[NumIntervals] [PositiveNumPoints1D];
[PositiveNumPoints1D] [PositiveSize];
[PositiveNumPoints1D] [NumIntervals];
[PositiveSize] [NumIntervals];
[PositiveSize] [PositiveNumPoints1D];
)]
impl From<In> for Out {
#[inline(always)]
fn from(value: In) -> Self {
Self(value.into_inner())
}
}
#[duplicate_item(
T;
[NumIntervals];
[PositiveSize];
[PositiveNumPoints1D];
)]
impl TryFrom<Size> for T {
type Error = ErrorsPositiveInt;
#[inline(always)]
fn try_from(size: Size) -> Result<Self, Self::Error> {
T::try_new(size.into_inner())
}
}
impl PositiveIntTrait for PositiveSize {}
impl PositiveIntTrait for NumIntervals {}
impl PositiveIntTrait for PositiveNumPoints1D {}
pub trait IndexId:
Copy
+ Clone
+ std::fmt::Debug
+ std::fmt::Display
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Hash
+ AsRef<usize>
+ IntoInner<InnerType = usize>
+ Serialize
+ DeserializeOwned
+ Sync
+ Send
{
fn new(value: usize) -> Self;
}
#[derive(Debug, Error)]
pub enum ErrorsPositiveInt {
#[error("The input value is zero (it must be strictly positive")]
ZeroValue {
backtrace: Backtrace,
},
}
#[duplicate_item(
T docstring;
[PositiveSize] ["Type indicating a ***positive*** size. It is basically a [`usize`] that cannot have a value smaller than 1"];
[NumIntervals] ["Type indicating a ***positive*** number of intervals. It is basically a [`usize`] that cannot have a value smaller than 1"];
[PositiveNumPoints1D] ["Type indicating a ***positive*** number of 1D points. It is basically a [`usize`] that cannot have a value smaller than 1"];
[Size] ["Type indicating a ***size***, i.e. a non-negative integer."];
[IntervalId] ["Type indicating the ID of an interval.\n\nThis type is a zero-based index used to identify intervals in a grid. It wraps a `usize` value and provides type safety for interval indexing operations, ensuring that only valid interval IDs are used in grid construction and manipulation."];
[CoordId] ["Type indicating the ID of a coordinate.\n\nThis type is a zero-based index used to identify coordinates in a grid. It wraps a `usize` value and provides type safety for coordinate indexing operations, ensuring that only valid coordinate IDs are used in grid construction and manipulation."];
)]
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Display,
AsRef,
Hash,
Serialize,
Deserialize,
IntoInner,
)]
#[doc = docstring]
#[repr(transparent)]
pub struct T(usize);
#[duplicate_item(
T docstring;
[Size] ["Build a [`Size`] instance from a `usize` value."];
[IntervalId] ["Build an [`IntervalId`] instance from a `usize` value."];
[CoordId] ["Build a [`CoordId`] instance from a `usize` value."];
)]
impl T {
#[inline(always)]
#[doc = docstring]
pub fn new(value: usize) -> Self {
T(value)
}
}
#[duplicate_item(
T;
[IntervalId];
[CoordId];
)]
impl IndexId for T {
#[inline(always)]
fn new(value: usize) -> Self {
Self(value)
}
}
#[duplicate_item(
T;
[PositiveSize];
[NumIntervals];
[PositiveNumPoints1D];
)]
impl TryNew for T {
type Error = ErrorsPositiveInt;
#[inline(always)]
fn try_new(value: usize) -> Result<Self, Self::Error> {
if value == 0 {
Err(ErrorsPositiveInt::ZeroValue {
backtrace: capture_backtrace(),
})
} else {
Ok(Self(value))
}
}
}
impl From<PositiveSize> for Size {
#[inline(always)]
fn from(item: PositiveSize) -> Self {
Size(item.into_inner())
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(bound(deserialize = "RealType: for<'a> Deserialize<'a>"))]
pub struct HashableScalar<RealType: RealScalar> {
value: RealType,
}
impl<RealType: RealScalar> Eq for HashableScalar<RealType> {}
impl<RealType: RealScalar> HashableScalar<RealType> {
#[must_use]
pub fn new(value: RealType) -> Self {
debug_assert!(
value.is_finite(),
"HashableScalar can only be constructed from finite real values!"
);
HashableScalar { value }
}
}
impl<RealType: RealScalar> Hash for HashableScalar<RealType> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.value.as_raw_ref().compute_hash(state);
}
}
#[cfg(test)]
mod tests {
use super::*;
mod interval_id {
use super::*;
#[test]
fn new() {
let v = IntervalId::new(0);
assert_eq!(*v.as_ref(), 0);
let v = IntervalId::new(5);
assert_eq!(*v.as_ref(), 5);
}
#[test]
fn equality_operator() {
let a = IntervalId::new(0);
let b = IntervalId::new(0);
assert!(a == b);
let c = IntervalId::new(5);
let d = IntervalId::new(5);
assert!(c == d);
}
#[test]
fn inequality_operator() {
let a = IntervalId::new(0);
let b = IntervalId::new(1);
assert!(a != b);
let c = IntervalId::new(5);
let d = IntervalId::new(10);
assert!(c != d);
}
#[test]
fn debug_trait() {
let id = IntervalId::new(3);
assert_eq!(format!("{:?}", id), "IntervalId(3)");
}
#[test]
#[allow(clippy::clone_on_copy)]
fn clone_trait() {
let id = IntervalId::new(4);
let cloned_id = id.clone();
assert_eq!(id, cloned_id);
}
#[test]
fn copy_trait() {
let id = IntervalId::new(2);
let copied_id = id;
assert_eq!(id, copied_id);
}
#[test]
fn partial_eq_trait() {
let id1 = IntervalId::new(6);
let id2 = IntervalId::new(6);
assert_eq!(id1, id2);
}
#[test]
fn partial_ord_trait() {
let id1 = IntervalId::new(3);
let id2 = IntervalId::new(5);
assert!(id1 < id2);
}
#[test]
fn display_trait() {
let id = IntervalId::new(7);
assert_eq!(format!("{}", id), "7");
}
#[test]
fn as_ref_trait() {
let id = IntervalId::new(8);
let inner: &usize = id.as_ref();
assert_eq!(*inner, 8);
}
#[test]
fn hash_trait() {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let id = IntervalId::new(9);
let mut hasher = DefaultHasher::new();
id.hash(&mut hasher);
let hash = hasher.finish();
let mut hasher2 = DefaultHasher::new();
id.hash(&mut hasher2);
let hash2 = hasher2.finish();
assert_eq!(hash, hash2);
}
#[test]
fn serialize_deserialize() {
let id = IntervalId::new(10);
let serialized = serde_json::to_string(&id).unwrap();
let deserialized: IntervalId = serde_json::from_str(&serialized).unwrap();
assert_eq!(id, deserialized);
}
}
mod num_intervals {
use super::*;
#[test]
fn try_new() {
let v = NumIntervals::try_new(1).unwrap();
assert_eq!(*v.as_ref(), 1);
let v = NumIntervals::try_new(5).unwrap();
assert_eq!(*v.as_ref(), 5);
let v = NumIntervals::try_new(0);
assert!(v.is_err());
}
#[test]
fn from_positive_size() {
let pos_size = PositiveSize::try_new(5).unwrap();
let num_intervals = NumIntervals::from(pos_size);
assert_eq!(*num_intervals.as_ref(), 5);
}
#[test]
fn equality_operator() {
let a = NumIntervals::try_new(1).unwrap();
let b = NumIntervals::try_new(1).unwrap();
assert!(a == b);
let c = NumIntervals::try_new(5).unwrap();
let d = NumIntervals::try_new(5).unwrap();
assert!(c == d);
}
#[test]
fn inequality_operator() {
let a = NumIntervals::try_new(1).unwrap();
let b = NumIntervals::try_new(2).unwrap();
assert!(a != b);
let c = NumIntervals::try_new(5).unwrap();
let d = NumIntervals::try_new(10).unwrap();
assert!(c != d);
}
#[test]
fn debug_trait() {
let num_intervals = NumIntervals::try_new(3).unwrap();
assert_eq!(format!("{:?}", num_intervals), "NumIntervals(3)");
}
#[test]
#[allow(clippy::clone_on_copy)]
fn clone_trait() {
let num_intervals = NumIntervals::try_new(4).unwrap();
let cloned_num_intervals = num_intervals.clone();
assert_eq!(num_intervals, cloned_num_intervals);
}
#[test]
fn copy_trait() {
let num_intervals = NumIntervals::try_new(2).unwrap();
let copied_num_intervals = num_intervals;
assert_eq!(num_intervals, copied_num_intervals);
}
#[test]
fn partial_eq_trait() {
let num_intervals1 = NumIntervals::try_new(6).unwrap();
let num_intervals2 = NumIntervals::try_new(6).unwrap();
assert_eq!(num_intervals1, num_intervals2);
}
#[test]
fn partial_ord_trait() {
let num_intervals1 = NumIntervals::try_new(3).unwrap();
let num_intervals2 = NumIntervals::try_new(5).unwrap();
assert!(num_intervals1 < num_intervals2);
}
#[test]
fn display_trait() {
let num_intervals = NumIntervals::try_new(7).unwrap();
assert_eq!(format!("{}", num_intervals), "7");
}
#[test]
fn as_ref_trait() {
let num_intervals = NumIntervals::try_new(8).unwrap();
let inner: &usize = num_intervals.as_ref();
assert_eq!(*inner, 8);
}
#[test]
fn hash_trait() {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let num_intervals = NumIntervals::try_new(9).unwrap();
let mut hasher = DefaultHasher::new();
num_intervals.hash(&mut hasher);
let hash = hasher.finish();
let mut hasher2 = DefaultHasher::new();
num_intervals.hash(&mut hasher2);
let hash2 = hasher2.finish();
assert_eq!(hash, hash2);
}
#[test]
fn serialize_deserialize() {
let num_intervals = NumIntervals::try_new(10).unwrap();
let serialized = serde_json::to_string(&num_intervals).unwrap();
let deserialized: NumIntervals = serde_json::from_str(&serialized).unwrap();
assert_eq!(num_intervals, deserialized);
}
}
mod positive_num_points_1d {
use super::*;
#[test]
fn try_new() {
let v = PositiveNumPoints1D::try_new(1).unwrap();
assert_eq!(*v.as_ref(), 1);
let v = PositiveNumPoints1D::try_new(5).unwrap();
assert_eq!(*v.as_ref(), 5);
let v = PositiveNumPoints1D::try_new(0);
assert!(v.is_err());
}
#[test]
fn equality_operator() {
let a = PositiveNumPoints1D::try_new(1).unwrap();
let b = PositiveNumPoints1D::try_new(1).unwrap();
assert!(a == b);
let c = PositiveNumPoints1D::try_new(5).unwrap();
let d = PositiveNumPoints1D::try_new(5).unwrap();
assert!(c == d);
}
#[test]
fn inequality_operator() {
let a = PositiveNumPoints1D::try_new(1).unwrap();
let b = PositiveNumPoints1D::try_new(2).unwrap();
assert!(a != b);
let c = PositiveNumPoints1D::try_new(5).unwrap();
let d = PositiveNumPoints1D::try_new(10).unwrap();
assert!(c != d);
}
#[test]
fn debug_trait() {
let num_points = PositiveNumPoints1D::try_new(3).unwrap();
assert_eq!(format!("{:?}", num_points), "PositiveNumPoints1D(3)");
}
#[test]
#[allow(clippy::clone_on_copy)]
fn clone_trait() {
let num_points = PositiveNumPoints1D::try_new(4).unwrap();
let cloned_num_points = num_points.clone();
assert_eq!(num_points, cloned_num_points);
}
#[test]
fn copy_trait() {
let num_points = PositiveNumPoints1D::try_new(2).unwrap();
let copied_num_points = num_points;
assert_eq!(num_points, copied_num_points);
}
#[test]
fn partial_eq_trait() {
let num_points1 = PositiveNumPoints1D::try_new(6).unwrap();
let num_points2 = PositiveNumPoints1D::try_new(6).unwrap();
assert_eq!(num_points1, num_points2);
}
#[test]
fn partial_ord_trait() {
let num_points1 = PositiveNumPoints1D::try_new(3).unwrap();
let num_points2 = PositiveNumPoints1D::try_new(5).unwrap();
assert!(num_points1 < num_points2);
}
#[test]
fn display_trait() {
let num_points = PositiveNumPoints1D::try_new(7).unwrap();
assert_eq!(format!("{}", num_points), "7");
}
#[test]
fn as_ref_trait() {
let num_points = PositiveNumPoints1D::try_new(8).unwrap();
let inner: &usize = num_points.as_ref();
assert_eq!(*inner, 8);
}
#[test]
fn hash_trait() {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let num_points = PositiveNumPoints1D::try_new(9).unwrap();
let mut hasher = DefaultHasher::new();
num_points.hash(&mut hasher);
let hash = hasher.finish();
let mut hasher2 = DefaultHasher::new();
num_points.hash(&mut hasher2);
let hash2 = hasher2.finish();
assert_eq!(hash, hash2);
}
#[test]
fn serialize_deserialize() {
let num_points = PositiveNumPoints1D::try_new(10).unwrap();
let serialized = serde_json::to_string(&num_points).unwrap();
let deserialized: PositiveNumPoints1D = serde_json::from_str(&serialized).unwrap();
assert_eq!(num_points, deserialized);
}
}
mod positive_size {
use super::*;
#[test]
fn try_new() {
let v = PositiveSize::try_new(1).unwrap();
assert_eq!(*v.as_ref(), 1);
let v = PositiveSize::try_new(5).unwrap();
assert_eq!(*v.as_ref(), 5);
let v = PositiveSize::try_new(0);
assert!(v.is_err());
}
#[test]
fn try_from_size() {
let size = Size::new(5);
let pos_size = PositiveSize::try_from(size).unwrap();
assert_eq!(*pos_size.as_ref(), 5);
let size_zero = Size::new(0);
let pos_size_zero = PositiveSize::try_from(size_zero);
assert!(pos_size_zero.is_err());
}
#[test]
fn equality_operator() {
let a = PositiveSize::try_new(1).unwrap();
let b = PositiveSize::try_new(1).unwrap();
assert!(a == b);
let c = PositiveSize::try_new(5).unwrap();
let d = PositiveSize::try_new(5).unwrap();
assert!(c == d);
}
#[test]
fn inequality_operator() {
let a = PositiveSize::try_new(1).unwrap();
let b = PositiveSize::try_new(2).unwrap();
assert!(a != b);
let c = PositiveSize::try_new(5).unwrap();
let d = PositiveSize::try_new(10).unwrap();
assert!(c != d);
}
#[test]
fn debug_trait() {
let size = PositiveSize::try_new(3).unwrap();
assert_eq!(format!("{:?}", size), "PositiveSize(3)");
}
#[test]
#[allow(clippy::clone_on_copy)]
fn clone_trait() {
let size = PositiveSize::try_new(4).unwrap();
let cloned_size = size.clone();
assert_eq!(size, cloned_size);
}
#[test]
fn copy_trait() {
let size = PositiveSize::try_new(2).unwrap();
let copied_size = size;
assert_eq!(size, copied_size);
}
#[test]
fn partial_eq_trait() {
let size1 = PositiveSize::try_new(6).unwrap();
let size2 = PositiveSize::try_new(6).unwrap();
assert_eq!(size1, size2);
}
#[test]
fn partial_ord_trait() {
let size1 = PositiveSize::try_new(3).unwrap();
let size2 = PositiveSize::try_new(5).unwrap();
assert!(size1 < size2);
}
#[test]
fn display_trait() {
let size = PositiveSize::try_new(7).unwrap();
assert_eq!(format!("{}", size), "7");
}
#[test]
fn as_ref_trait() {
let size = PositiveSize::try_new(8).unwrap();
let inner: &usize = size.as_ref();
assert_eq!(*inner, 8);
}
#[test]
fn hash_trait() {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let size = PositiveSize::try_new(9).unwrap();
let mut hasher = DefaultHasher::new();
size.hash(&mut hasher);
let hash = hasher.finish();
let mut hasher2 = DefaultHasher::new();
size.hash(&mut hasher2);
let hash2 = hasher2.finish();
assert_eq!(hash, hash2);
}
#[test]
fn serialize_deserialize() {
let size = PositiveSize::try_new(10).unwrap();
let serialized = serde_json::to_string(&size).unwrap();
let deserialized: PositiveSize = serde_json::from_str(&serialized).unwrap();
assert_eq!(size, deserialized);
}
}
mod size {
use super::*;
#[test]
fn new() {
let v = Size::new(0);
assert_eq!(*v.as_ref(), 0);
let v = Size::new(5);
assert_eq!(*v.as_ref(), 5);
}
#[test]
fn equality_operator() {
let a = Size::new(0);
let b = Size::new(0);
assert!(a == b);
let c = Size::new(5);
let d = Size::new(5);
assert!(c == d);
}
#[test]
fn inequality_operator() {
let a = Size::new(0);
let b = Size::new(1);
assert!(a != b);
let c = Size::new(5);
let d = Size::new(10);
assert!(c != d);
}
#[test]
fn debug_trait() {
let size = Size::new(3);
assert_eq!(format!("{:?}", size), "Size(3)");
}
#[test]
#[allow(clippy::clone_on_copy)]
fn clone_trait() {
let size = Size::new(4);
let cloned_size = size.clone();
assert_eq!(size, cloned_size);
}
#[test]
fn copy_trait() {
let size = Size::new(2);
let copied_size = size;
assert_eq!(size, copied_size);
}
#[test]
fn partial_eq_trait() {
let size1 = Size::new(6);
let size2 = Size::new(6);
assert_eq!(size1, size2);
}
#[test]
fn partial_ord_trait() {
let size1 = Size::new(3);
let size2 = Size::new(5);
assert!(size1 < size2);
}
#[test]
fn display_trait() {
let size = Size::new(7);
assert_eq!(format!("{}", size), "7");
}
#[test]
fn as_ref_trait() {
let size = Size::new(8);
let inner: &usize = size.as_ref();
assert_eq!(*inner, 8);
}
#[test]
fn hash_trait() {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let size = Size::new(9);
let mut hasher = DefaultHasher::new();
size.hash(&mut hasher);
let hash = hasher.finish();
let mut hasher2 = DefaultHasher::new();
size.hash(&mut hasher2);
let hash2 = hasher2.finish();
assert_eq!(hash, hash2);
}
#[test]
fn serialize_deserialize() {
let size = Size::new(10);
let serialized = serde_json::to_string(&size).unwrap();
let deserialized: Size = serde_json::from_str(&serialized).unwrap();
assert_eq!(size, deserialized);
}
#[test]
fn from_positive_size() {
let pos_size = PositiveSize::try_new(5).unwrap();
let size = Size::from(pos_size);
assert_eq!(*size.as_ref(), 5);
}
}
}