#[macro_export]
macro_rules! define_index {
($name:ident, $inner:ty, $doc:expr) => {
#[doc = $doc]
#[repr(transparent)]
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
serde::Serialize,
serde::Deserialize,
)]
pub struct $name($inner);
impl $name {
pub const fn from(var: $inner) -> Self {
Self(var)
}
pub const fn get(&self) -> $inner {
self.0
}
}
impl std::ops::Deref for $name {
type Target = $inner;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<$inner> for $name {
fn from(value: $inner) -> Self {
$name(value)
}
}
impl From<$name> for $inner {
fn from(value: $name) -> Self {
value.0
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
};
}
#[macro_export]
macro_rules! define_nonzero_count {
($name:ident, $base:ty, $doc:expr) => {
#[doc = $doc]
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
serde::Serialize,
serde::Deserialize,
)]
pub struct $name {
value: $base,
}
impl $name {
pub fn new(value: $base) -> Result<Self, FeagiDataError> {
if value == 0 {
return Err(FeagiDataError::BadParameters(
"Count cannot be zero!".into(),
));
}
Ok($name { value })
}
}
impl TryFrom<$base> for $name {
type Error = FeagiDataError;
fn try_from(value: $base) -> Result<Self, FeagiDataError> {
$name::new({ value })
}
}
impl From<$name> for $base {
fn from(value: $name) -> $base {
value.value
}
}
impl std::ops::Deref for $name {
type Target = $base;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
self.value.fmt(f)
}
}
};
}
#[macro_export]
macro_rules! define_xy_coordinates {
($name:ident, $var_type:ty, $friendly_name:expr, $doc_string:expr) => {
#[doc = $doc_string]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Copy, serde::Serialize, serde::Deserialize)]
pub struct $name {
pub x: $var_type,
pub y: $var_type,
}
impl $name {
pub fn new(x: $var_type, y: $var_type) -> Self {
Self { x, y }
}
}
impl From<$name> for ($var_type, $var_type) {
fn from(value: $name) -> Self {
(value.x, value.y)
}
}
impl From<($var_type, $var_type)> for $name {
fn from(value: ($var_type, $var_type)) -> Self {
$name::new(value.0, value.1)
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}({}, {})", $friendly_name, self.x, self.y)
}
}
};
}
#[macro_export]
macro_rules! define_xy_dimensions {
($name:ident, $var_type:ty, $friendly_name:expr, $invalid_zero_value:expr, $doc_string:expr) => {
#[doc = $doc_string]
#[derive(Clone, Debug, PartialEq, Copy, Hash, Eq, serde::Serialize, serde::Deserialize)]
pub struct $name {
pub width: $var_type,
pub height: $var_type,
}
impl $name {
pub fn new(x: $var_type, y: $var_type) -> Result<Self, FeagiDataError> {
if x == $invalid_zero_value || y == $invalid_zero_value {
return Err(FeagiDataError::BadParameters(format!(
"Value cannot be {:?} in a {:?}!",
$invalid_zero_value, $friendly_name
)));
}
Ok(Self {
width: x,
height: y,
})
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}<{}, {}>", $friendly_name, self.width, self.height)
}
}
impl From<$name> for ($var_type, $var_type) {
fn from(value: $name) -> Self {
(value.width, value.height)
}
}
impl TryFrom<($var_type, $var_type)> for $name {
type Error = FeagiDataError;
fn try_from(value: ($var_type, $var_type)) -> Result<Self, Self::Error> {
if value.0 == $invalid_zero_value {
return Err(FeagiDataError::BadParameters(format!(
"X value cannot be zero!"
)));
}
if value.1 == $invalid_zero_value {
return Err(FeagiDataError::BadParameters(format!(
"Y value cannot be zero!"
)));
}
Ok(Self {
width: value.0,
height: value.1,
})
}
}
};
}
#[macro_export]
macro_rules! define_xyz_coordinates {
($name:ident, $var_type:ty, $friendly_name:expr, $doc_string:expr) => {
#[doc = $doc_string]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Copy, serde::Serialize, serde::Deserialize)]
pub struct $name {
pub x: $var_type,
pub y: $var_type,
pub z: $var_type,
}
impl $name {
pub fn new(x: $var_type, y: $var_type, z: $var_type) -> Self {
Self { x, y, z }
}
}
impl From<$name> for ($var_type, $var_type, $var_type) {
fn from(value: $name) -> Self {
(value.x, value.y, value.z)
}
}
impl From<($var_type, $var_type, $var_type)> for $name {
fn from(value: ($var_type, $var_type, $var_type)) -> Self {
$name::new(value.0, value.1, value.2)
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}({}, {}, {})", $friendly_name, self.x, self.y, self.z)
}
}
};
}
#[macro_export]
macro_rules! define_xyz_dimensions {
($name:ident, $var_type:ty, $friendly_name:expr, $invalid_zero_value:expr, $doc_string:expr) => {
#[doc = $doc_string]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Copy, serde::Serialize, serde::Deserialize)]
pub struct $name {
pub width: $var_type,
pub height: $var_type,
pub depth: $var_type,
}
impl $name {
pub fn new(x: $var_type, y: $var_type, z: $var_type) -> Result<Self, FeagiDataError> {
if x == $invalid_zero_value || y == $invalid_zero_value || z == $invalid_zero_value
{
return Err(FeagiDataError::BadParameters(format!(
"Value cannot be {:?} in a {:?}!",
$invalid_zero_value, $friendly_name
)));
}
Ok(Self {
width: x,
height: y,
depth: z,
})
}
pub fn from_tuple(
tuple: ($var_type, $var_type, $var_type),
) -> Result<Self, FeagiDataError> {
Self::new(tuple.0, tuple.1, tuple.2)
}
pub fn to_tuple(&self) -> ($var_type, $var_type, $var_type) {
(self.width, self.height, self.depth)
}
pub fn number_elements(&self) -> $var_type {
self.width * self.height * self.depth
}
pub fn volume(&self) -> $var_type {
self.number_elements()
}
pub fn total_voxels(&self) -> $var_type {
self.number_elements()
}
pub fn contains(&self, pos: ($var_type, $var_type, $var_type)) -> bool {
pos.0 < self.width && pos.1 < self.height && pos.2 < self.depth
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{}<{}, {}, {}>",
$friendly_name, self.width, self.height, self.depth
)
}
}
impl From<$name> for ($var_type, $var_type, $var_type) {
fn from(value: $name) -> Self {
(value.width, value.height, value.depth)
}
}
impl TryFrom<($var_type, $var_type, $var_type)> for $name {
type Error = FeagiDataError;
fn try_from(value: ($var_type, $var_type, $var_type)) -> Result<Self, Self::Error> {
if value.0 == $invalid_zero_value {
return Err(FeagiDataError::BadParameters(format!(
"X value cannot be zero!"
)));
}
if value.1 == $invalid_zero_value {
return Err(FeagiDataError::BadParameters(format!(
"Y value cannot be zero!"
)));
}
if value.2 == $invalid_zero_value {
return Err(FeagiDataError::BadParameters(format!(
"Z value cannot be zero!"
)));
}
Ok(Self {
width: value.0,
height: value.1,
depth: value.2,
})
}
}
};
}
#[macro_export]
macro_rules! define_xyz_mapping {
($XYZ_a:ident, $XYZ_b:ident) => {
impl From<$XYZ_a> for $XYZ_b {
fn from(a: $XYZ_a) -> Self {
$XYZ_b::new(a.width, a.height, a.depth).unwrap()
}
}
impl From<$XYZ_b> for $XYZ_a {
fn from(b: $XYZ_b) -> Self {
$XYZ_a::new(b.width, b.height, b.depth).unwrap()
}
}
};
}
#[macro_export]
macro_rules! define_xyz_dimension_range {
($name:ident, $var_type:ty, $coordinate_type:ty, $friendly_name:expr, $doc:expr) => {
#[doc = $doc]
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct $name {
pub width: std::ops::Range<$var_type>,
pub height: std::ops::Range<$var_type>,
pub depth: std::ops::Range<$var_type>,
}
impl $name {
pub fn new(
x: std::ops::Range<$var_type>,
y: std::ops::Range<$var_type>,
z: std::ops::Range<$var_type>,
) -> Result<Self, FeagiDataError> {
Ok($name {
width: x,
height: y,
depth: z,
})
}
pub fn verify_coordinate_within_range(
&self,
coordinate: &$coordinate_type,
) -> Result<(), FeagiDataError> {
if self.width.contains(&coordinate.width)
&& self.height.contains(&coordinate.height)
&& self.depth.contains(&coordinate.depth)
{
return Ok(());
}
Err(FeagiDataError::BadParameters(format!(
"Coordinate {:?} is not contained by this given range of {:?}!",
coordinate, self
)))
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{}<{:?}, {:?}, {:?}>",
$friendly_name, self.width, self.height, self.depth
)
}
}
};
}