Create a gist now

Instantly share code, notes, and snippets.

@huonw /slice_iter.rs
Last active Aug 29, 2015

What would you like to do?
// from http://www.reddit.com/r/rust/comments/27s7ei/comparing_knn_in_rust/ci43euj
use std::kinds::marker;
use std::cmp;
use std::mem;
use std::mem::transmute;
// cribbed from both core::iter and core::slice
struct SliceZipIterator<'lt, A, B> {
a: *A,
a_end: *A,
b: *B,
marker: marker::ContravariantLifetime<'lt>
}
#[inline]
unsafe fn slice_offset<T>(p: *T, n: uint) -> *T {
if mem::size_of::<T>() == 0 {
transmute(p as uint + n)
} else {
p.offset(n as int)
}
}
impl<'lt, A, B> Iterator<(&'lt A, &'lt B)> for SliceZipIterator<'lt, A, B> {
#[inline]
fn next(&mut self) -> Option<(&'lt A, &'lt B)> {
if self.a == self.a_end {
return None
} else {
unsafe {
let old = (self.a, self.b);
self.a = slice_offset(self.a, 1);
self.b = slice_offset(self.b, 1);
let r: (&'lt A, &'lt B) = transmute(old);
Some(r)
}
}
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
let diff = (self.a_end as uint) - (self.a as uint);
let size = mem::size_of::<A>();
let exact = diff / (if size == 0 {1} else {size});
(exact, Some(exact))
}
}
fn slice_zip<'lt, A, B>(a: &'lt [A], b: &'lt [B]) -> SliceZipIterator<'lt, A, B> {
unsafe {
SliceZipIterator {
a: a.as_ptr(),
a_end: slice_offset(a.as_ptr(), cmp::min(a.len(), b.len())),
b: b.as_ptr(),
marker: marker::ContravariantLifetime
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment