#[derive(Debug, Clone, Copy)]
pub enum Transpose {
None,
Ordinary,
}
impl Transpose {
pub fn is_transpose(&self) -> bool {
match self {
Self::None => false,
Self::Ordinary => true,
}
}
pub fn forward<T>(&self, if_none: T, if_transpose: T) -> T {
match self {
Self::None => if_none,
Self::Ordinary => if_transpose,
}
}
pub fn call<F, G, T>(&self, if_none: F, if_transpose: G) -> T
where
F: Fn() -> T,
G: Fn() -> T,
{
match self {
Self::None => if_none(),
Self::Ordinary => if_transpose(),
}
}
}
#[cfg(test)]
mod tests {
use std::sync::atomic::{AtomicBool, Ordering};
use super::*;
#[test]
fn test_is_transpose() {
assert!(!(Transpose::None).is_transpose());
assert!((Transpose::Ordinary).is_transpose());
}
#[test]
fn test_forward() {
assert_eq!((Transpose::None).forward(1, 2), 1);
assert_eq!((Transpose::Ordinary).forward(1, 2), 2);
}
#[test]
fn test_call() {
let a_called = AtomicBool::new(false);
let b_called = AtomicBool::new(false);
let a = || {
a_called.store(true, Ordering::Relaxed);
1
};
let b = || {
b_called.store(true, Ordering::Relaxed);
2
};
assert_eq!((Transpose::None).call(a, b), 1);
assert!(a_called.load(Ordering::Relaxed));
assert!(!b_called.load(Ordering::Relaxed));
let a_called = AtomicBool::new(false);
let b_called = AtomicBool::new(false);
let a = || {
a_called.store(true, Ordering::Relaxed);
1
};
let b = || {
b_called.store(true, Ordering::Relaxed);
2
};
assert_eq!((Transpose::Ordinary).call(a, b), 2);
assert!(!a_called.load(Ordering::Relaxed));
assert!(b_called.load(Ordering::Relaxed));
}
}