mod sealed {
pub trait Sealed {}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(i32)]
pub enum DatatypeTag {
F32 = 0,
F64 = 1,
I32 = 2,
I64 = 3,
U8 = 4,
U32 = 5,
U64 = 6,
}
pub trait MpiDatatype: sealed::Sealed + Copy + Send + 'static {
const TAG: DatatypeTag;
}
macro_rules! impl_mpi_datatype {
($ty:ty, $tag:expr) => {
impl sealed::Sealed for $ty {}
impl MpiDatatype for $ty {
const TAG: DatatypeTag = $tag;
}
};
}
impl_mpi_datatype!(f32, DatatypeTag::F32);
impl_mpi_datatype!(f64, DatatypeTag::F64);
impl_mpi_datatype!(i32, DatatypeTag::I32);
impl_mpi_datatype!(i64, DatatypeTag::I64);
impl_mpi_datatype!(u8, DatatypeTag::U8);
impl_mpi_datatype!(u32, DatatypeTag::U32);
impl_mpi_datatype!(u64, DatatypeTag::U64);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tag_values_match_c_defines() {
assert_eq!(DatatypeTag::F32 as i32, 0);
assert_eq!(DatatypeTag::F64 as i32, 1);
assert_eq!(DatatypeTag::I32 as i32, 2);
assert_eq!(DatatypeTag::I64 as i32, 3);
assert_eq!(DatatypeTag::U8 as i32, 4);
assert_eq!(DatatypeTag::U32 as i32, 5);
assert_eq!(DatatypeTag::U64 as i32, 6);
}
#[test]
fn datatype_tags_match_c_defines() {
assert_eq!(f32::TAG as i32, 0); assert_eq!(f64::TAG as i32, 1); assert_eq!(i32::TAG as i32, 2); assert_eq!(i64::TAG as i32, 3); assert_eq!(u8::TAG as i32, 4); assert_eq!(u32::TAG as i32, 5); assert_eq!(u64::TAG as i32, 6); }
#[test]
fn datatype_tag_values_are_sequential() {
let tags = [
DatatypeTag::F32,
DatatypeTag::F64,
DatatypeTag::I32,
DatatypeTag::I64,
DatatypeTag::U8,
DatatypeTag::U32,
DatatypeTag::U64,
];
for (i, tag) in tags.iter().enumerate() {
assert_eq!(*tag as i32, i as i32, "Tag {tag:?} should have value {i}");
}
}
#[test]
fn trait_is_implemented() {
fn assert_mpi_datatype<T: MpiDatatype>() {}
assert_mpi_datatype::<f32>();
assert_mpi_datatype::<f64>();
assert_mpi_datatype::<i32>();
assert_mpi_datatype::<i64>();
assert_mpi_datatype::<u8>();
assert_mpi_datatype::<u32>();
assert_mpi_datatype::<u64>();
}
#[test]
fn datatype_tag_debug_format() {
assert_eq!(format!("{:?}", DatatypeTag::F32), "F32");
assert_eq!(format!("{:?}", DatatypeTag::F64), "F64");
assert_eq!(format!("{:?}", DatatypeTag::I32), "I32");
assert_eq!(format!("{:?}", DatatypeTag::I64), "I64");
assert_eq!(format!("{:?}", DatatypeTag::U8), "U8");
assert_eq!(format!("{:?}", DatatypeTag::U32), "U32");
assert_eq!(format!("{:?}", DatatypeTag::U64), "U64");
}
#[test]
fn datatype_tag_clone_hash() {
use std::collections::HashSet;
let tag = DatatypeTag::F64;
let cloned = tag;
assert_eq!(cloned, DatatypeTag::F64);
let mut set = HashSet::new();
set.insert(DatatypeTag::F32);
set.insert(DatatypeTag::F64);
set.insert(DatatypeTag::F32); assert_eq!(set.len(), 2);
}
}