Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  zipslices.rs   Sprache: unbekannt

 
use std::cmp;

// Note: There are different ways to implement ZipSlices.
// This version performed the best in benchmarks.
//
// I also implemented a version with three pointers (tptr, tend, uptr),
// that mimiced slice::Iter and only checked bounds by using tptr == tend,
// but that was inferior to this solution.

/// An iterator which iterates two slices simultaneously.
///
/// `ZipSlices` acts like a double-ended `.zip()` iterator.
///
/// It was intended to be more efficient than `.zip()`, and it was, then
/// rustc changed how it optimizes so it can not promise improved performance
/// at this time.
///
/// Note that elements past the end of the shortest of the two slices are ignored.
///
/// Iterator element type for `ZipSlices<T, U>` is `(T::Item, U::Item)`. For example,
/// for a `ZipSlices<&'a [A], &'b mut [B]>`, the element type is `(&'a A, &'b mut B)`.
#[derive(Clone)]
pub struct ZipSlices<T, U> {
    t: T,
    u: U,
    len: usize,
    index: usize,
}

impl<'a, 'b, A, B> ZipSlices<&'a [A], &'b [B]> {
    /// Create a new `ZipSlices` from slices `a` and `b`.
    ///
    /// Act like a double-ended `.zip()` iterator, but more efficiently.
    ///
    /// Note that elements past the end of the shortest of the two slices are ignored.
    #[inline(always)]
    pub fn new(a: &'a [A], b: &'b [B]) -> Self {
        let minl = cmp::min(a.len(), b.len());
        ZipSlices {
            t: a,
            u: b,
            len: minl,
            index: 0,
        }
    }
}

impl<T, U> ZipSlices<T, U>
    where T: Slice,
          U: Slice
{
    /// Create a new `ZipSlices` from slices `a` and `b`.
    ///
    /// Act like a double-ended `.zip()` iterator, but more efficiently.
    ///
    /// Note that elements past the end of the shortest of the two slices are ignored.
    #[inline(always)]
    pub fn from_slices(a: T, b: U) -> Self {
        let minl = cmp::min(a.len(), b.len());
        ZipSlices {
            t: a,
            u: b,
            len: minl,
            index: 0,
        }
    }
}

impl<T, U> Iterator for ZipSlices<T, U>
    where T: Slice,
          U: Slice
{
    type Item = (T::Item, U::Item);

    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            if self.index >= self.len {
                None
            } else {
                let i = self.index;
                self.index += 1;
                Some((
                    self.t.get_unchecked(i),
                    self.u.get_unchecked(i)))
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len - self.index;
        (len, Some(len))
    }
}

impl<T, U> DoubleEndedIterator for ZipSlices<T, U>
    where T: Slice,
          U: Slice
{
    #[inline(always)]
    fn next_back(&mut self) -> Option<Self::Item> {
        unsafe {
            if self.index >= self.len {
                None
            } else {
                self.len -= 1;
                let i = self.len;
                Some((
                    self.t.get_unchecked(i),
                    self.u.get_unchecked(i)))
            }
        }
    }
}

impl<T, U> ExactSizeIterator for ZipSlices<T, U>
    where T: Slice,
          U: Slice
{}

unsafe impl<T, U> Slice for ZipSlices<T, U>
    where T: Slice,
          U: Slice
{
    type Item = (T::Item, U::Item);

    fn len(&self) -> usize {
        self.len - self.index
    }

    unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
        (self.t.get_unchecked(i),
         self.u.get_unchecked(i))
    }
}

/// A helper trait to let `ZipSlices` accept both `&[T]` and `&mut [T]`.
///
/// Unsafe trait because:
///
/// - Implementors must guarantee that `get_unchecked` is valid for all indices `0..len()`.
pub unsafe trait Slice {
    /// The type of a reference to the slice's elements
    type Item;
    #[doc(hidden)]
    fn len(&self) -> usize;
    #[doc(hidden)]
    unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item;
}

unsafe impl<'a, T> Slice for &'a [T] {
    type Item = &'a T;
    #[inline(always)]
    fn len(&self) -> usize { (**self).len() }
    #[inline(always)]
    unsafe fn get_unchecked(&mut self, i: usize) -> &'a T {
        debug_assert!(i < self.len());
        (**self).get_unchecked(i)
    }
}

unsafe impl<'a, T> Slice for &'a mut [T] {
    type Item = &'a mut T;
    #[inline(always)]
    fn len(&self) -> usize { (**self).len() }
    #[inline(always)]
    unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T {
        debug_assert!(i < self.len());
        // override the lifetime constraints of &mut &'a mut [T]
        (*(*self as *mut [T])).get_unchecked_mut(i)
    }
}

#[test]
fn zipslices() {

    let xs = [1, 2, 3, 4, 5, 6];
    let ys = [1, 2, 3, 7];
    ::itertools::assert_equal(ZipSlices::new(&xs, &ys), xs.iter().zip(&ys));

    let xs = [1, 2, 3, 4, 5, 6];
    let mut ys = [0; 6];
    for (x, y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) {
        *y = *x;
    }
    ::itertools::assert_equal(&xs, &ys);
}

[ Dauer der Verarbeitung: 0.22 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge