Skip to content

Commit c9651f9

Browse files
committed
Now works on beta/stable
Until rust-lang/rust#35729 stabilizes, we directly import and implement the `SliceIndex` trait, which lets us work correctly on stable!
1 parent f87b67b commit c9651f9

File tree

4 files changed

+154
-6
lines changed

4 files changed

+154
-6
lines changed

.travis.yml

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ env:
1919
before_install: . vendor/bindgen/ci/before_install.sh
2020
rust:
2121
- nightly
22+
- beta
23+
- stable
2224
cache: cargo
2325
matrix:
2426
allow_failures:

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ibverbs"
3-
version = "0.2.4"
3+
version = "0.3.0"
44

55
description = "Bindings for RDMA ibverbs through rdma-core"
66
readme = "README.md"

src/lib.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
//! [1]: http://www.rdmamojo.com/2012/05/18/libibverbs/
6262
6363
#![deny(missing_docs)]
64-
#![feature(slice_get_slice)]
6564

6665
use std::marker::PhantomData;
6766
use std::ptr;
@@ -96,6 +95,10 @@ pub use ffi::IBV_ACCESS_REMOTE_READ;
9695
/// Enable Remote Atomic Operation Access (if supported).
9796
pub use ffi::IBV_ACCESS_REMOTE_ATOMIC;
9897

98+
/// Because `std::slice::SliceIndex` is still unstable, we follow @alexcrichton's suggestion in
99+
/// https://github.com/rust-lang/rust/issues/35729 and implement it ourselves.
100+
mod sliceindex;
101+
99102
/// Get list of available RDMA devices.
100103
///
101104
/// # Errors
@@ -1082,9 +1085,9 @@ impl<'res> QueuePair<'res> {
10821085
range: R,
10831086
wr_id: u64)
10841087
-> io::Result<()>
1085-
where R: std::slice::SliceIndex<[T], Output = [T]>
1088+
where R: sliceindex::SliceIndex<[T], Output = [T]>
10861089
{
1087-
let range = &mr[range];
1090+
let range = range.index(&mr);
10881091
let mut sge = ffi::ibv_sge {
10891092
addr: range.as_ptr() as u64,
10901093
length: (mem::size_of::<T>() * range.len()) as u32,
@@ -1165,9 +1168,9 @@ impl<'res> QueuePair<'res> {
11651168
range: R,
11661169
wr_id: u64)
11671170
-> io::Result<()>
1168-
where R: std::slice::SliceIndex<[T], Output = [T]>
1171+
where R: sliceindex::SliceIndex<[T], Output = [T]>
11691172
{
1170-
let range = &mr[range];
1173+
let range = range.index(&mr);
11711174
let mut sge = ffi::ibv_sge {
11721175
addr: range.as_ptr() as u64,
11731176
length: (mem::size_of::<T>() * range.len()) as u32,

src/sliceindex.rs

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
use std::ops;
2+
3+
pub trait SliceIndex<T: ?Sized> {
4+
/// The output type returned by methods.
5+
type Output: ?Sized;
6+
7+
/// Returns a shared reference to the output at this location, without
8+
/// performing any bounds checking.
9+
unsafe fn get_unchecked(self, slice: &T) -> &Self::Output;
10+
11+
/// Returns a shared reference to the output at this location, panicking
12+
/// if out of bounds.
13+
fn index(self, slice: &T) -> &Self::Output;
14+
}
15+
16+
impl<T> SliceIndex<[T]> for usize {
17+
type Output = T;
18+
19+
#[inline]
20+
unsafe fn get_unchecked(self, slice: &[T]) -> &T {
21+
&*slice.as_ptr().offset(self as isize)
22+
}
23+
24+
#[inline]
25+
fn index(self, slice: &[T]) -> &T {
26+
// NB: use intrinsic indexing
27+
&(*slice)[self]
28+
}
29+
}
30+
31+
#[inline(never)]
32+
#[cold]
33+
fn slice_index_len_fail(index: usize, len: usize) -> ! {
34+
panic!("index {} out of range for slice of length {}", index, len);
35+
}
36+
37+
#[inline(never)]
38+
#[cold]
39+
fn slice_index_order_fail(index: usize, end: usize) -> ! {
40+
panic!("slice index starts at {} but ends at {}", index, end);
41+
}
42+
43+
impl<T> SliceIndex<[T]> for ops::Range<usize> {
44+
type Output = [T];
45+
46+
#[inline]
47+
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
48+
use std::slice::from_raw_parts;
49+
from_raw_parts(slice.as_ptr().offset(self.start as isize),
50+
self.end - self.start)
51+
}
52+
53+
#[inline]
54+
fn index(self, slice: &[T]) -> &[T] {
55+
if self.start > self.end {
56+
slice_index_order_fail(self.start, self.end);
57+
} else if self.end > slice.len() {
58+
slice_index_len_fail(self.end, slice.len());
59+
}
60+
unsafe { self.get_unchecked(slice) }
61+
}
62+
}
63+
64+
impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
65+
type Output = [T];
66+
67+
#[inline]
68+
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
69+
(0..self.end).get_unchecked(slice)
70+
}
71+
72+
#[inline]
73+
fn index(self, slice: &[T]) -> &[T] {
74+
(0..self.end).index(slice)
75+
}
76+
}
77+
78+
impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
79+
type Output = [T];
80+
81+
#[inline]
82+
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
83+
(self.start..slice.len()).get_unchecked(slice)
84+
}
85+
86+
#[inline]
87+
fn index(self, slice: &[T]) -> &[T] {
88+
(self.start..slice.len()).index(slice)
89+
}
90+
}
91+
92+
impl<T> SliceIndex<[T]> for ops::RangeFull {
93+
type Output = [T];
94+
95+
#[inline]
96+
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
97+
slice
98+
}
99+
100+
#[inline]
101+
fn index(self, slice: &[T]) -> &[T] {
102+
slice
103+
}
104+
}
105+
106+
// nightly only:
107+
//
108+
// impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
109+
// type Output = [T];
110+
//
111+
// #[inline]
112+
// unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
113+
// match self {
114+
// ops::RangeInclusive::Empty { .. } => &[],
115+
// ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_unchecked(slice),
116+
// }
117+
// }
118+
//
119+
// #[inline]
120+
// fn index(self, slice: &[T]) -> &[T] {
121+
// match self {
122+
// ops::RangeInclusive::Empty { .. } => &[],
123+
// ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
124+
// panic!("attempted to index slice up to maximum usize");
125+
// }
126+
// ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index(slice),
127+
// }
128+
// }
129+
// }
130+
//
131+
// impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
132+
// type Output = [T];
133+
//
134+
// #[inline]
135+
// unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
136+
// (0...self.end).get_unchecked(slice)
137+
// }
138+
//
139+
// #[inline]
140+
// fn index(self, slice: &[T]) -> &[T] {
141+
// (0...self.end).index(slice)
142+
// }
143+
// }

0 commit comments

Comments
 (0)