Skip to content

Commit 525f65e

Browse files
author
Clark Gaebel
committed
Add RingBuf::as_slices as per collections reform v2.
See: rust-lang/rfcs#509 Not sure if this is allowed to land before the RFC. Either way, it's here for review. r? @gankro cc: @bfops
1 parent 0efafac commit 525f65e

File tree

1 file changed

+111
-2
lines changed

1 file changed

+111
-2
lines changed

src/libcollections/ring_buf.rs

+111-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,13 @@ impl<T> Default for RingBuf<T> {
7878
impl<T> RingBuf<T> {
7979
/// Turn ptr into a slice
8080
#[inline]
81-
unsafe fn buffer_as_slice(&self) -> &[T] {
81+
unsafe fn buffer_as_slice<'a>(&'a self) -> &'a [T] {
82+
mem::transmute(RawSlice { data: self.ptr as *const T, len: self.cap })
83+
}
84+
85+
/// Turn ptr into a mut slice
86+
#[inline]
87+
unsafe fn buffer_as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
8288
mem::transmute(RawSlice { data: self.ptr as *const T, len: self.cap })
8389
}
8490

@@ -413,6 +419,48 @@ impl<T> RingBuf<T> {
413419
}
414420
}
415421

422+
/// Returns a pair of slices which contain, in order, the contents of the
423+
/// `RingBuf`.
424+
#[inline]
425+
#[unstable = "matches collection reform specification, waiting for dust to settle"]
426+
pub fn as_slices<'a>(&'a self) -> (&'a [T], &'a [T]) {
427+
unsafe {
428+
let contiguous = self.is_contiguous();
429+
let buf = self.buffer_as_slice();
430+
if contiguous {
431+
let (empty, buf) = buf.split_at(0);
432+
(buf[self.tail..self.head], empty)
433+
} else {
434+
let (mid, right) = buf.split_at(self.tail);
435+
let (left, _) = mid.split_at(self.head);
436+
(right, left)
437+
}
438+
}
439+
}
440+
441+
/// Returns a pair of slices which contain, in order, the contents of the
442+
/// `RingBuf`.
443+
#[inline]
444+
#[unstable = "matches collection reform specification, waiting for dust to settle"]
445+
pub fn as_mut_slices<'a>(&'a mut self) -> (&'a mut [T], &'a mut [T]) {
446+
unsafe {
447+
let contiguous = self.is_contiguous();
448+
let head = self.head;
449+
let tail = self.tail;
450+
let buf = self.buffer_as_mut_slice();
451+
452+
if contiguous {
453+
let (empty, buf) = buf.split_at_mut(0);
454+
(buf[mut tail..head], empty)
455+
} else {
456+
let (mid, right) = buf.split_at_mut(tail);
457+
let (left, _) = mid.split_at_mut(head);
458+
459+
(right, left)
460+
}
461+
}
462+
}
463+
416464
/// Returns the number of elements in the `RingBuf`.
417465
///
418466
/// # Examples
@@ -663,6 +711,11 @@ impl<T> RingBuf<T> {
663711
}
664712
}
665713

714+
#[inline]
715+
fn is_contiguous(&self) -> bool {
716+
self.tail <= self.head
717+
}
718+
666719
/// Inserts an element at position `i` within the ringbuf. Whichever
667720
/// end is closer to the insertion point will be moved to make room,
668721
/// and all the affected elements will be moved to new positions.
@@ -715,7 +768,7 @@ impl<T> RingBuf<T> {
715768
let distance_to_tail = i;
716769
let distance_to_head = self.len() - i;
717770

718-
let contiguous = self.tail <= self.head;
771+
let contiguous = self.is_contiguous();
719772

720773
match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
721774
(true, true, _) if i == 0 => {
@@ -2132,4 +2185,60 @@ mod tests {
21322185
ring.pop_front();
21332186
assert_eq!(ring.front(), None);
21342187
}
2188+
2189+
#[test]
2190+
fn test_as_slices() {
2191+
let mut ring: RingBuf<int> = RingBuf::with_capacity(127);
2192+
let cap = ring.capacity() as int;
2193+
let first = cap/2;
2194+
let last = cap - first;
2195+
for i in range(0, first) {
2196+
ring.push_back(i);
2197+
2198+
let (left, right) = ring.as_slices();
2199+
let expected: Vec<_> = range(0, i+1).collect();
2200+
assert_eq!(left, expected);
2201+
assert_eq!(right, []);
2202+
}
2203+
2204+
for j in range(-last, 0) {
2205+
ring.push_front(j);
2206+
let (left, right) = ring.as_slices();
2207+
let expected_left: Vec<_> = range(-last, j+1).rev().collect();
2208+
let expected_right: Vec<_> = range(0, first).collect();
2209+
assert_eq!(left, expected_left);
2210+
assert_eq!(right, expected_right);
2211+
}
2212+
2213+
assert_eq!(ring.len() as int, cap);
2214+
assert_eq!(ring.capacity() as int, cap);
2215+
}
2216+
2217+
#[test]
2218+
fn test_as_mut_slices() {
2219+
let mut ring: RingBuf<int> = RingBuf::with_capacity(127);
2220+
let cap = ring.capacity() as int;
2221+
let first = cap/2;
2222+
let last = cap - first;
2223+
for i in range(0, first) {
2224+
ring.push_back(i);
2225+
2226+
let (left, right) = ring.as_mut_slices();
2227+
let expected: Vec<_> = range(0, i+1).collect();
2228+
assert_eq!(left, expected);
2229+
assert_eq!(right, []);
2230+
}
2231+
2232+
for j in range(-last, 0) {
2233+
ring.push_front(j);
2234+
let (left, right) = ring.as_mut_slices();
2235+
let expected_left: Vec<_> = range(-last, j+1).rev().collect();
2236+
let expected_right: Vec<_> = range(0, first).collect();
2237+
assert_eq!(left, expected_left);
2238+
assert_eq!(right, expected_right);
2239+
}
2240+
2241+
assert_eq!(ring.len() as int, cap);
2242+
assert_eq!(ring.capacity() as int, cap);
2243+
}
21352244
}

0 commit comments

Comments
 (0)