shuffled_iter/
iter.rs

1use std::u32::MAX as UMAX;
2use rand::Rng;
3use super::ShuffledIter as SI;
4
5/// This trait may be used to obtain an instance of `ShuffledIter`. It should
6/// always be implemented generically for all types implementing `rand::Rng`,
7/// that is for all random number generators (which is the case for this library).
8///
9/// As such, an instance of `ShuffledIter` may be obtained by calling `iter_shuffled`
10/// with a suitable argument on any random number generator, given that `ShuffledIterGen`
11/// is in scope.
12///
13/// An implementation of this trait is provided by this library for the following
14/// agument types:
15///
16/// * all ranges of integer types (ie. `0i8..`, `..10u16`, `10..20`)
17/// * slices of any kind
18pub trait ShuffledIterGen<T>: Rng {
19    type Iter: Iterator;
20
21    fn iter_shuffled(&mut self, T) -> Self::Iter;
22}
23
24#[derive(Copy, Clone)]
25pub struct Slice<'a, T: 'a> {
26    iter: SI,
27    slice: &'a [T],
28}
29
30impl<'a, T: 'a, R: Rng> ShuffledIterGen<&'a [T]> for R {
31    type Iter = Slice<'a, T>;
32
33    fn iter_shuffled(&mut self, slice: &'a [T]) -> Slice<'a, T> {
34        let len = slice.len();
35
36        if len == 0 { panic!("slice must not be empty") }
37        if len > UMAX as usize + 1 { panic!("slice may contain at most u32::MAX + 1 elements") }
38
39        Slice {
40            iter: SI::new((len - 1) as u32, self),
41            slice: slice,
42        }
43    }
44}
45
46impl<'a, T> Iterator for Slice<'a, T> {
47    type Item = &'a T;
48
49    #[inline]
50    fn next(&mut self) -> Option<&'a T> {
51        self.iter.next().map(|i| &self.slice[i as usize])
52    }
53}
54
55macro_rules! impl_range {($prim:ident) => {
56    mod $prim {
57        #[derive(Copy, Clone)]
58        pub struct Iter {
59            iter: ::ShuffledIter,
60            offset: $prim,
61        }
62
63        pub fn new<R: ::rand::Rng>(rng: &mut R, min: $prim, max: $prim) -> Iter {
64            if min > max { panic!("min > max") }
65
66            if (max - min) as u64 > ::std::u32::MAX as u64 { panic!("range must contain at most u32::MAX + 1 elements") }
67
68            Iter {
69                iter: ::ShuffledIter::new((max - min) as u32, rng),
70                offset: min,
71            }
72        }
73
74        impl Iterator for Iter {
75            type Item = $prim;
76
77            #[inline]
78            fn next(&mut self) -> Option<$prim> {
79                self.iter.next().map(|u| u as $prim + self.offset)
80            }
81        }
82    }
83
84    impl<R: Rng> ShuffledIterGen<::std::ops::Range<$prim>> for R {
85        type Iter = $prim::Iter;
86
87        fn iter_shuffled(&mut self, range: ::std::ops::Range<$prim>) -> $prim::Iter {
88            if range.end <= range.start { panic!("range must contain at least one element") }
89            $prim::new(self, range.start, range.end - 1)
90        }
91    }
92
93    impl<R: Rng> ShuffledIterGen<::std::ops::RangeFrom<$prim>> for R {
94        type Iter = $prim::Iter;
95
96        fn iter_shuffled(&mut self, range: ::std::ops::RangeFrom<$prim>) -> $prim::Iter {
97            $prim::new(self, range.start, ::std::$prim::MAX)
98        }
99    }
100
101    impl<R: Rng> ShuffledIterGen<::std::ops::RangeTo<$prim>> for R {
102        type Iter = $prim::Iter;
103
104        fn iter_shuffled(&mut self, range: ::std::ops::RangeTo<$prim>) -> $prim::Iter {
105            if range.end == ::std::$prim::MIN { panic!("range must contain at least one element") }
106            $prim::new(self, ::std::$prim::MIN, range.end - 1)
107        }
108    }
109}}
110
111macro_rules! impl_ranges {($($prim:ident),+) => {$(
112    impl_range!($prim);
113)*}}
114
115impl_ranges!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
116
117#[cfg(test)]
118#[path = "iter_tests.rs"]
119mod iter_tests;