]>
git.proxmox.com Git - rustc.git/blob - src/vendor/itertools-0.6.5/benches/extra/zipslices.rs
3 // Note: There are different ways to implement ZipSlices.
4 // This version performed the best in benchmarks.
6 // I also implemented a version with three pointes (tptr, tend, uptr),
7 // that mimiced slice::Iter and only checked bounds by using tptr == tend,
8 // but that was inferior to this solution.
10 /// An iterator which iterates two slices simultaneously.
12 /// `ZipSlices` acts like a double-ended `.zip()` iterator.
14 /// It was intended to be more efficient than `.zip()`, and it was, then
15 /// rustc changed how it optimizes so it can not promise improved performance
18 /// Note that elements past the end of the shortest of the two slices are ignored.
20 /// Iterator element type for `ZipSlices<T, U>` is `(T::Item, U::Item)`. For example,
21 /// for a `ZipSlices<&'a [A], &'b mut [B]>`, the element type is `(&'a A, &'b mut B)`.
23 pub struct ZipSlices
<T
, U
> {
30 impl<'a
, 'b
, A
, B
> ZipSlices
<&'a
[A
], &'b
[B
]> {
31 /// Create a new `ZipSlices` from slices `a` and `b`.
33 /// Act like a double-ended `.zip()` iterator, but more efficiently.
35 /// Note that elements past the end of the shortest of the two slices are ignored.
37 pub fn new(a
: &'a
[A
], b
: &'b
[B
]) -> Self {
38 let minl
= cmp
::min(a
.len(), b
.len());
48 impl<T
, U
> ZipSlices
<T
, U
>
52 /// Create a new `ZipSlices` from slices `a` and `b`.
54 /// Act like a double-ended `.zip()` iterator, but more efficiently.
56 /// Note that elements past the end of the shortest of the two slices are ignored.
58 pub fn from_slices(a
: T
, b
: U
) -> Self {
59 let minl
= cmp
::min(a
.len(), b
.len());
69 impl<T
, U
> Iterator
for ZipSlices
<T
, U
>
73 type Item
= (T
::Item
, U
::Item
);
76 fn next(&mut self) -> Option
<Self::Item
> {
78 if self.index
>= self.len
{
84 self.t
.get_unchecked(i
),
85 self.u
.get_unchecked(i
)))
91 fn size_hint(&self) -> (usize, Option
<usize>) {
92 let len
= self.len
- self.index
;
97 impl<T
, U
> DoubleEndedIterator
for ZipSlices
<T
, U
>
102 fn next_back(&mut self) -> Option
<Self::Item
> {
104 if self.index
>= self.len
{
110 self.t
.get_unchecked(i
),
111 self.u
.get_unchecked(i
)))
117 impl<T
, U
> ExactSizeIterator
for ZipSlices
<T
, U
>
122 unsafe impl<T
, U
> Slice
for ZipSlices
<T
, U
>
126 type Item
= (T
::Item
, U
::Item
);
128 fn len(&self) -> usize {
129 self.len
- self.index
132 unsafe fn get_unchecked(&mut self, i
: usize) -> Self::Item
{
133 (self.t
.get_unchecked(i
),
134 self.u
.get_unchecked(i
))
138 /// A helper trait to let `ZipSlices` accept both `&[T]` and `&mut [T]`.
140 /// Unsafe trait because:
142 /// - Implementors must guarantee that `get_unchecked` is valid for all indices `0..len()`.
143 pub unsafe trait Slice
{
144 /// The type of a reference to the slice's elements
147 fn len(&self) -> usize;
149 unsafe fn get_unchecked(&mut self, i
: usize) -> Self::Item
;
152 unsafe impl<'a
, T
> Slice
for &'a
[T
] {
155 fn len(&self) -> usize { (**self).len() }
157 unsafe fn get_unchecked(&mut self, i
: usize) -> &'a T
{
158 debug_assert
!(i
< self.len());
159 (**self).get_unchecked(i
)
163 unsafe impl<'a
, T
> Slice
for &'a
mut [T
] {
164 type Item
= &'a
mut T
;
166 fn len(&self) -> usize { (**self).len() }
168 unsafe fn get_unchecked(&mut self, i
: usize) -> &'a
mut T
{
169 debug_assert
!(i
< self.len());
170 // override the lifetime constraints of &mut &'a mut [T]
171 (*(*self as *mut [T
])).get_unchecked_mut(i
)
178 let xs
= [1, 2, 3, 4, 5, 6];
179 let ys
= [1, 2, 3, 7];
180 ::itertools
::assert_equal(ZipSlices
::new(&xs
, &ys
), xs
.iter().zip(&ys
));
182 let xs
= [1, 2, 3, 4, 5, 6];
184 for (x
, y
) in ZipSlices
::from_slices(&xs
[..], &mut ys
[..]) {
187 ::itertools
::assert_equal(&xs
, &ys
);