//! Dependency tuple trait and implementations. //! //! This module defines the DepsTuple trait that allows specifying dependencies in //! various forms (handles, builders, tuples). It uses macro-generated implementations //! for different tuple sizes. //! //! This trait is internal and not meant for external implementation. Users should only //! use the provided implementations. use crate::builder::TaskBuilder; use crate::task::Task; use crate::types::{NodeId, TaskHandle}; trait IntoNodeRef { type Output; fn into_node_ref(self) -> NodeId; } impl IntoNodeRef for &TaskHandle { type Output = T; fn into_node_ref(self) -> NodeId { self.id } } impl IntoNodeRef for TaskHandle { type Output = T; fn into_node_ref(self) -> NodeId { self.id } } impl<'runner, Tk: Task, Deps> IntoNodeRef for TaskBuilder<'runner, Tk, Deps> { type Output = Tk::Output; fn into_node_ref(self) -> NodeId { self.id } } pub(crate) trait DepsTuple { fn to_node_ids(self) -> Vec; } // Implementation for unit (no dependencies) impl DepsTuple<()> for () { fn to_node_ids(self) -> Vec { Vec::new() } } // Implementation for single dependency (all forms) impl DepsTuple<(T::Output,)> for T where T: IntoNodeRef, { fn to_node_ids(self) -> Vec { vec![self.into_node_ref()] } } impl DepsTuple for (T,) where T: IntoNodeRef, { fn to_node_ids(self) -> Vec { vec![self.0.into_node_ref()] } } /// Macro to implement DepsTuple for different tuple sizes. /// /// This macro exists because Rust lacks variadic generics - we need separate implementations /// for each tuple size. /// /// This allows flexible dependency specification: /// ```ignore /// // Using handles /// task.depends_on((&handle_a, &handle_b)) /// /// // Using builders directly /// task.depends_on((&dag.add_task(TaskA), &dag.add_task(TaskB))) /// ``` macro_rules! impl_deps_tuple { ($($T:ident),+) => { // For tuples of any combination of &TaskHandle, TaskHandle, and TaskBuilder impl<$($T: IntoNodeRef),+> DepsTuple<($($T::Output,)+)> for ($($T,)+) { #[allow(non_snake_case)] fn to_node_ids(self) -> Vec { let ($($T,)+) = self; vec![$($T.into_node_ref(),)+] } } }; } // Generate DepsTuple implementations for tuples of size 2-8. // Supporting up to 8 elements covers the vast majority of use cases. impl_deps_tuple!(T1, T2); impl_deps_tuple!(T1, T2, T3); impl_deps_tuple!(T1, T2, T3, T4); impl_deps_tuple!(T1, T2, T3, T4, T5); impl_deps_tuple!(T1, T2, T3, T4, T5, T6); impl_deps_tuple!(T1, T2, T3, T4, T5, T6, T7); impl_deps_tuple!(T1, T2, T3, T4, T5, T6, T7, T8); #[cfg(test)] mod tests;