1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! Macros for delegating newtype iterators to inner types.

// Note: these place `impl` bounds at the end, as token gobbling is the only way
// I know how to consume an arbitrary list of constraints, with `$($args:tt)*`.

/// Create a parallel iterator which simply wraps an inner type and delegates
/// all methods inward.  The item type is parsed from the inner type.
///
/// The implementation of `IntoParallelIterator` should be added separately.
///
/// # Example
///
/// ```
/// delegate_iterator!{
///     #[doc = "Move items from `MyCollection` in parallel"]
///     MyIntoIter<T, U> => vec::IntoIter<(T, U)>,
///     impl<T: Ord + Send, U: Send>
/// }
/// ```
macro_rules! delegate_iterator {
    ($( #[ $attr:meta ] )+
     $iter:ident < $( $i:tt ),* > => $( $inner:ident )::+ < $item:ty > ,
     impl $( $args:tt )*
     ) => {
        delegate_iterator_item!{
            $( #[ $attr ] )+
            $iter < $( $i ),* > => $( $inner )::+ < $item > : $item ,
            impl $( $args )*
        }
    }
}

/// Create an indexed parallel iterator which simply wraps an inner type and
/// delegates all methods inward.  The item type is parsed from the inner type.
macro_rules! delegate_indexed_iterator {
    ($( #[ $attr:meta ] )+
     $iter:ident < $( $i:tt ),* > => $( $inner:ident )::+ < $item:ty > ,
     impl $( $args:tt )*
     ) => {
        delegate_indexed_iterator_item!{
            $( #[ $attr ] )+
            $iter < $( $i ),* > => $( $inner )::+ < $item > : $item ,
            impl $( $args )*
        }
    }
}

/// Create a parallel iterator which simply wraps an inner type and delegates
/// all methods inward.  The item type is explicitly specified.
///
/// The implementation of `IntoParallelIterator` should be added separately.
///
/// # Example
///
/// ```
/// delegate_iterator_item!{
///     #[doc = "Iterate items from `MyCollection` in parallel"]
///     MyIter<'a, T, U> => slice::Iter<'a, (T, U)>: &'a (T, U),
///     impl<'a, T: Ord + Sync, U: Sync>
/// }
/// ```
macro_rules! delegate_iterator_item {
    ($( #[ $attr:meta ] )+
     $iter:ident < $( $i:tt ),* > => $inner:ty : $item:ty,
     impl $( $args:tt )*
     ) => {
        $( #[ $attr ] )+
        pub struct $iter $( $args )* {
            inner: $inner,
        }

        impl $( $args )* ParallelIterator for $iter < $( $i ),* > {
            type Item = $item;

            fn drive_unindexed<C>(self, consumer: C) -> C::Result
                where C: UnindexedConsumer<Self::Item>
            {
                self.inner.drive_unindexed(consumer)
            }

            fn opt_len(&mut self) -> Option<usize> {
                self.inner.opt_len()
            }
        }
    }
}

/// Create an indexed parallel iterator which simply wraps an inner type and
/// delegates all methods inward.  The item type is explicitly specified.
macro_rules! delegate_indexed_iterator_item {
    ($( #[ $attr:meta ] )+
     $iter:ident < $( $i:tt ),* > => $inner:ty : $item:ty,
     impl $( $args:tt )*
     ) => {
        delegate_iterator_item!{
            $( #[ $attr ] )+
            $iter < $( $i ),* > => $inner : $item ,
            impl $( $args )*
        }

        impl $( $args )* BoundedParallelIterator for $iter < $( $i ),* > {
            fn upper_bound(&mut self) -> usize {
                self.inner.upper_bound()
            }

            fn drive<C>(self, consumer: C) -> C::Result
                where C: Consumer<Self::Item>
            {
                self.inner.drive(consumer)
            }
        }

        impl $( $args )* ExactParallelIterator for $iter < $( $i ),* > {
            fn len(&mut self) -> usize {
                self.inner.len()
            }
        }

        impl $( $args )* IndexedParallelIterator for $iter < $( $i ),* > {
            fn with_producer<CB>(self, callback: CB) -> CB::Output
                where CB: ProducerCallback<Self::Item>
            {
                self.inner.with_producer(callback)
            }
        }
    }
}