#[macro_export]
macro_rules! pipex {
($input:expr $(=> $($rest:tt)+)?) => {{
let initial_results = $input
.into_iter()
.map(|x| Ok(x))
.collect::<Vec<Result<_, ()>>>();
pipex!(@process initial_results $(=> $($rest)+)?)
}};
(@process $input:expr => |$var:ident| $body:expr $(=> $($rest:tt)+)?) => {{
let sync_results = $input
.into_iter()
.map(|item_result| {
match item_result {
Ok($var) => {
use $crate::traits::IntoPipelineItem;
($body).into_pipeline_item()
},
Err(e) => {
let mut error_string = format!("{:?}", e);
while error_string.starts_with("\"") && error_string.ends_with("\"") {
error_string = error_string[1..error_string.len()-1].to_string();
}
<_ as $crate::CreateError<String>>::create_error(error_string)
}
}
})
.collect::<Vec<_>>();
use $crate::PipelineResultHandler;
let iter_result = sync_results.handle_pipeline_results();
pipex!(@process iter_result $(=> $($rest)+)?)
}};
(@process $input:expr => async |$var:ident| $body:block $(=> $($rest:tt)+)?) => {{
let result = {
async {
#[cfg(feature = "async")]
{
let futures_results = $crate::futures::future::join_all(
$input.into_iter().map(|item| async move {
match item {
Ok($var) => {
$body
},
Err(e) => {
let mut error_string = format!("{:?}", e);
while error_string.starts_with("\"") && error_string.ends_with("\"") {
error_string = error_string[1..error_string.len()-1].to_string();
}
<_ as $crate::CreateError<String>>::create_error(error_string)
}
}
})
).await;
use $crate::PipelineResultHandler;
futures_results.handle_pipeline_results()
}
#[cfg(not(feature = "async"))]
{
compile_error!("Async pipeline operations require the 'async' feature to be enabled");
}
}
};
pipex!(@process result.await $(=> $($rest)+)?)
}};
(@process $input:expr => ||| |$var:ident| $body:expr $(=> $($rest:tt)+)?) => {{
let result = {
#[cfg(feature = "parallel")]
{
use $crate::rayon::prelude::*;
let parallel_results_intermediate = $input.into_par_iter().map(|item_result| {
match item_result {
Ok($var) => {
use $crate::traits::IntoPipelineItem;
($body).into_pipeline_item()
},
Err(e) => {
let mut error_string = format!("{:?}", e);
while error_string.starts_with("\"") && error_string.ends_with("\"") {
error_string = error_string[1..error_string.len()-1].to_string();
}
<_ as $crate::CreateError<String>>::create_error(error_string)
}
}
}).collect::<Vec<_>>();
use $crate::PipelineResultHandler;
parallel_results_intermediate.handle_pipeline_results()
}
#[cfg(not(feature = "parallel"))]
{
compile_error!("Parallel pipeline operations require the 'parallel' feature to be enabled");
}
};
pipex!(@process result $(=> $($rest)+)?)
}};
(@process $input:expr => gpu ||| |$var:ident| $body:expr $(=> $($rest:tt)+)?) => {{
let result = {
#[cfg(feature = "gpu")]
{
async {
let mut gpu_inputs = Vec::new();
let mut input_items = Vec::new();
let mut success_indices = Vec::new();
for (idx, item_result) in $input.into_iter().enumerate() {
match item_result {
Ok(item) => {
gpu_inputs.push(item);
success_indices.push(idx);
input_items.push(Ok(())); },
Err(e) => {
input_items.push(Err(e)); }
}
}
let transpiled_kernel = $crate::gpu::transpile_rust_expression(stringify!($body), stringify!($var));
let gpu_results = if !gpu_inputs.is_empty() {
let gpu_inputs_clone = gpu_inputs.clone();
match $crate::gpu::execute_gpu_kernel(gpu_inputs, &transpiled_kernel).await {
Ok(results) => results,
Err(gpu_error) => {
eprintln!("⚠️ GPU execution failed, falling back to CPU: {}", gpu_error);
gpu_inputs_clone.into_iter().map(|$var| $body).collect::<Vec<_>>()
}
}
} else {
Vec::new()
};
let mut gpu_idx = 0;
input_items.into_iter().map(|item_result| {
match item_result {
Ok(_) => {
let result = Ok(gpu_results[gpu_idx].clone());
gpu_idx += 1;
result
},
Err(e) => Err(format!("{:?}", e)), }
}).collect::<Vec<_>>()
}
}
#[cfg(not(feature = "gpu"))]
{
use $crate::rayon::prelude::*;
$input.into_par_iter().map(|item_result| {
match item_result {
Ok($var) => Ok($body),
Err(e) => Err(format!("{:?}", e)),
}
}).collect::<Vec<_>>()
}
};
pipex!(@process result.await $(=> $($rest)+)?)
}};
(@process $input:expr => gpu $kernel:literal |$var:ident: Vec<$t:ty>| $body:block $(=> $($rest:tt)+)?) => {{
let result = {
#[cfg(feature = "gpu")]
{
async {
let mut gpu_inputs = Vec::new();
let mut input_items = Vec::new();
let mut success_indices = Vec::new();
for (idx, item_result) in $input.into_iter().enumerate() {
match item_result {
Ok(item) => {
gpu_inputs.push(item);
success_indices.push(idx);
input_items.push(Ok(())); },
Err(e) => {
input_items.push(Err(e)); }
}
}
let gpu_results = if !gpu_inputs.is_empty() {
match $crate::gpu::execute_gpu_kernel(gpu_inputs, $kernel).await {
Ok(results) => results,
Err(gpu_error) => {
let error_msg = format!("GPU execution failed: {}", gpu_error);
return input_items.into_iter().map(|item_result| {
match item_result {
Ok(_) => Err(error_msg.clone()),
Err(e) => Err(format!("{:?}", e)), }
}).collect::<Vec<_>>();
}
}
} else {
Vec::new()
};
let mut gpu_idx = 0;
input_items.into_iter().map(|item_result| {
match item_result {
Ok(_) => {
let result = Ok(gpu_results[gpu_idx].clone());
gpu_idx += 1;
result
},
Err(e) => Err(format!("{:?}", e)), }
}).collect::<Vec<_>>()
}
}
#[cfg(not(feature = "gpu"))]
{
compile_error!("GPU pipeline operations require the 'gpu' feature to be enabled");
}
};
pipex!(@process result.await $(=> $($rest)+)?)
}};
(@process $input:expr) => {{
$input.into_iter().collect::<Vec<_>>()
}};
}
#[macro_export]
macro_rules! register_strategies {
($($handler:ident),+ $(,)? for <$t:ty, $e:ty>) => {
$(
$crate::register_strategy::<$t, $e>(stringify!($handler), $handler::handle_results);
)+
};
}