1use std::u32::MAX as UMAX;
2use rand::Rng;
3use super::ShuffledIter as SI;
4
5pub 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;