Skip to content

Commit

Permalink
Now works on beta/stable
Browse files Browse the repository at this point in the history
Until rust-lang/rust#35729 stabilizes, we directly import and implement
the `SliceIndex` trait, which lets us work correctly on stable!
  • Loading branch information
jonhoo committed May 11, 2017
1 parent f87b67b commit c9651f9
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 6 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ env:
before_install: . vendor/bindgen/ci/before_install.sh
rust:
- nightly
- beta
- stable
cache: cargo
matrix:
allow_failures:
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ibverbs"
version = "0.2.4"
version = "0.3.0"

description = "Bindings for RDMA ibverbs through rdma-core"
readme = "README.md"
Expand Down
13 changes: 8 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
//! [1]: http://www.rdmamojo.com/2012/05/18/libibverbs/
#![deny(missing_docs)]
#![feature(slice_get_slice)]

use std::marker::PhantomData;
use std::ptr;
Expand Down Expand Up @@ -96,6 +95,10 @@ pub use ffi::IBV_ACCESS_REMOTE_READ;
/// Enable Remote Atomic Operation Access (if supported).
pub use ffi::IBV_ACCESS_REMOTE_ATOMIC;

/// Because `std::slice::SliceIndex` is still unstable, we follow @alexcrichton's suggestion in
/// https://github.com/rust-lang/rust/issues/35729 and implement it ourselves.
mod sliceindex;

/// Get list of available RDMA devices.
///
/// # Errors
Expand Down Expand Up @@ -1082,9 +1085,9 @@ impl<'res> QueuePair<'res> {
range: R,
wr_id: u64)
-> io::Result<()>
where R: std::slice::SliceIndex<[T], Output = [T]>
where R: sliceindex::SliceIndex<[T], Output = [T]>
{
let range = &mr[range];
let range = range.index(&mr);
let mut sge = ffi::ibv_sge {
addr: range.as_ptr() as u64,
length: (mem::size_of::<T>() * range.len()) as u32,
Expand Down Expand Up @@ -1165,9 +1168,9 @@ impl<'res> QueuePair<'res> {
range: R,
wr_id: u64)
-> io::Result<()>
where R: std::slice::SliceIndex<[T], Output = [T]>
where R: sliceindex::SliceIndex<[T], Output = [T]>
{
let range = &mr[range];
let range = range.index(&mr);
let mut sge = ffi::ibv_sge {
addr: range.as_ptr() as u64,
length: (mem::size_of::<T>() * range.len()) as u32,
Expand Down
143 changes: 143 additions & 0 deletions src/sliceindex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use std::ops;

pub trait SliceIndex<T: ?Sized> {
/// The output type returned by methods.
type Output: ?Sized;

/// Returns a shared reference to the output at this location, without
/// performing any bounds checking.
unsafe fn get_unchecked(self, slice: &T) -> &Self::Output;

/// Returns a shared reference to the output at this location, panicking
/// if out of bounds.
fn index(self, slice: &T) -> &Self::Output;
}

impl<T> SliceIndex<[T]> for usize {
type Output = T;

#[inline]
unsafe fn get_unchecked(self, slice: &[T]) -> &T {
&*slice.as_ptr().offset(self as isize)
}

#[inline]
fn index(self, slice: &[T]) -> &T {
// NB: use intrinsic indexing
&(*slice)[self]
}
}

#[inline(never)]
#[cold]
fn slice_index_len_fail(index: usize, len: usize) -> ! {
panic!("index {} out of range for slice of length {}", index, len);
}

#[inline(never)]
#[cold]
fn slice_index_order_fail(index: usize, end: usize) -> ! {
panic!("slice index starts at {} but ends at {}", index, end);
}

impl<T> SliceIndex<[T]> for ops::Range<usize> {
type Output = [T];

#[inline]
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
use std::slice::from_raw_parts;
from_raw_parts(slice.as_ptr().offset(self.start as isize),
self.end - self.start)
}

#[inline]
fn index(self, slice: &[T]) -> &[T] {
if self.start > self.end {
slice_index_order_fail(self.start, self.end);
} else if self.end > slice.len() {
slice_index_len_fail(self.end, slice.len());
}
unsafe { self.get_unchecked(slice) }
}
}

impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
type Output = [T];

#[inline]
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
(0..self.end).get_unchecked(slice)
}

#[inline]
fn index(self, slice: &[T]) -> &[T] {
(0..self.end).index(slice)
}
}

impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
type Output = [T];

#[inline]
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
(self.start..slice.len()).get_unchecked(slice)
}

#[inline]
fn index(self, slice: &[T]) -> &[T] {
(self.start..slice.len()).index(slice)
}
}

impl<T> SliceIndex<[T]> for ops::RangeFull {
type Output = [T];

#[inline]
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
slice
}

#[inline]
fn index(self, slice: &[T]) -> &[T] {
slice
}
}

// nightly only:
//
// impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
// type Output = [T];
//
// #[inline]
// unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
// match self {
// ops::RangeInclusive::Empty { .. } => &[],
// ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_unchecked(slice),
// }
// }
//
// #[inline]
// fn index(self, slice: &[T]) -> &[T] {
// match self {
// ops::RangeInclusive::Empty { .. } => &[],
// ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
// panic!("attempted to index slice up to maximum usize");
// }
// ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index(slice),
// }
// }
// }
//
// impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
// type Output = [T];
//
// #[inline]
// unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
// (0...self.end).get_unchecked(slice)
// }
//
// #[inline]
// fn index(self, slice: &[T]) -> &[T] {
// (0...self.end).index(slice)
// }
// }

0 comments on commit c9651f9

Please sign in to comment.