pub trait Execute {
fn execute(self);
}
pub trait ExecuteWith<TArg: ?Sized> {
fn execute_with(self, arg: &TArg);
}
pub trait ExecuteWithMut<TArg: ?Sized> {
fn execute_with_mut(self, arg: &mut TArg);
}
impl<T> Execute for T
where
T: IntoIterator,
T::Item: Execute,
{
fn execute(self) {
self.into_iter().for_each(move |item| item.execute());
}
}
impl<T, TArg: ?Sized> ExecuteWith<TArg> for T
where
T: IntoIterator,
T::Item: ExecuteWith<TArg>,
{
fn execute_with(self, arg: &TArg) {
self.into_iter()
.for_each(move |item| item.execute_with(arg));
}
}
impl<T, TArg: ?Sized> ExecuteWithMut<TArg> for T
where
T: IntoIterator,
T::Item: ExecuteWithMut<TArg>,
{
fn execute_with_mut(self, arg: &mut TArg) {
self.into_iter()
.for_each(move |item| item.execute_with_mut(arg));
}
}
#[cfg(test)]
mod tests {
use crate::{Execute, ExecuteWith, ExecuteWithMut};
use enum_pipeline_derive::{Execute, ExecuteWith, ExecuteWithMut};
#[derive(Execute)]
enum VoidDispatchPipeline {
#[handler(VoidDispatchPipeline::handle_one)]
One,
#[handler(handle_two)]
Two,
}
static mut VOID_ONE_COUNT: i32 = 0;
static mut VOID_TWO_COUNT: i32 = 0;
impl VoidDispatchPipeline {
fn handle_one() {
unsafe {
VOID_ONE_COUNT += 1;
}
}
fn handle_two() {
unsafe {
VOID_TWO_COUNT += 1;
}
}
}
#[test]
fn void_dispatch_works() {
let pipeline = vec![VoidDispatchPipeline::One, VoidDispatchPipeline::Two];
pipeline.execute();
unsafe {
assert_eq!(1, VOID_ONE_COUNT);
assert_eq!(1, VOID_TWO_COUNT);
}
}
enum RefDataPipeline {
One(i32),
Two,
}
static mut REF_ONE_VALUE: i32 = 0;
static mut REF_TWO_COUNT: i32 = 0;
struct RefDataPipelineData {
mult: i32,
}
impl RefDataPipeline {
fn handle_one(v: i32, arg: &RefDataPipelineData) {
unsafe {
REF_ONE_VALUE += v * arg.mult;
}
}
fn handle_two(_arg: &RefDataPipelineData) {
unsafe {
REF_TWO_COUNT += 1;
}
}
}
impl ExecuteWith<RefDataPipelineData> for RefDataPipeline {
fn execute_with(self, arg: &RefDataPipelineData) {
match self {
RefDataPipeline::One(f) => RefDataPipeline::handle_one(f, arg),
RefDataPipeline::Two => RefDataPipeline::handle_two(arg),
}
}
}
#[test]
fn ref_data_pipeline_works() {
let pipeline = vec![RefDataPipeline::One(24), RefDataPipeline::Two];
let data = RefDataPipelineData { mult: 2 };
pipeline.execute_with(&data);
unsafe {
assert_eq!(48, REF_ONE_VALUE);
assert_eq!(1, REF_TWO_COUNT);
}
}
enum MutDataPipeline {
One(i32),
Two,
}
#[derive(Default)]
struct MutDataPipelineData {
one_value: i32,
two_count: i32,
}
impl ExecuteWithMut<MutDataPipelineData> for MutDataPipeline {
fn execute_with_mut(self, arg: &mut MutDataPipelineData) {
match self {
MutDataPipeline::One(i) => arg.one_value += i,
MutDataPipeline::Two => arg.two_count += 1,
}
}
}
#[test]
fn mut_data_pipeline_works() {
let pipeline = vec![MutDataPipeline::One(12), MutDataPipeline::Two];
let mut data = MutDataPipelineData::default();
pipeline.execute_with_mut(&mut data);
assert_eq!(12, data.one_value);
assert_eq!(1, data.two_count);
}
struct MacroRefPipelineData {}
#[derive(ExecuteWith)]
#[execute_with(MacroRefPipelineData)]
enum MacroRefPipeline {
#[handler(handle_a)]
A,
#[handler(handle_b)]
B,
}
static mut MACRO_REF_ONE_COUNT: i32 = 0;
static mut MACRO_REF_TWO_COUNT: i32 = 0;
impl MacroRefPipeline {
fn handle_a(_data: &MacroRefPipelineData) {
unsafe {
MACRO_REF_ONE_COUNT += 1;
}
}
fn handle_b(_data: &MacroRefPipelineData) {
unsafe {
MACRO_REF_TWO_COUNT += 1;
}
}
}
#[test]
fn macro_ref_pipeline_works() {
vec![MacroRefPipeline::A, MacroRefPipeline::B].execute_with(&MacroRefPipelineData {});
unsafe {
assert_eq!(1, MACRO_REF_ONE_COUNT);
assert_eq!(1, MACRO_REF_TWO_COUNT);
}
}
#[derive(Default)]
struct MacroMutRefData {
a_count: i32,
b_count: i32,
}
#[derive(ExecuteWithMut)]
#[execute_with(MacroMutRefData)]
enum MacroMutRefPipeline {
#[handler(handle_a)]
A(i32),
#[handler(handle_b)]
B,
}
impl MacroMutRefPipeline {
fn handle_a(_i: i32, arg: &mut MacroMutRefData) {
arg.a_count += 1;
}
fn handle_b(arg: &mut MacroMutRefData) {
arg.b_count += 1;
}
}
#[test]
fn macro_mut_pipeline_works() {
let mut arg = MacroMutRefData::default();
vec![MacroMutRefPipeline::A(23), MacroMutRefPipeline::B].execute_with_mut(&mut arg);
assert_eq!(1, arg.a_count);
assert_eq!(1, arg.b_count);
}
#[derive(Default)]
struct MutRefData {
a_count: i32,
b_count: i32,
}
enum MutRefPipeline {
A(i32),
B,
}
impl ExecuteWithMut<MutRefData> for MutRefPipeline {
fn execute_with_mut(self, arg: &mut MutRefData) {
match self {
MutRefPipeline::A(_i) => arg.a_count += 1,
MutRefPipeline::B => arg.b_count += 1,
}
}
}
#[test]
fn _mut_pipeline_works() {
let mut arg = MutRefData::default();
vec![MutRefPipeline::A(23), MutRefPipeline::B].execute_with_mut(&mut arg);
assert_eq!(1, arg.a_count);
assert_eq!(1, arg.b_count);
}
}