Skip to content

Commit

Permalink
Slice methods and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
agerasev committed Apr 8, 2023
1 parent 4d3d51b commit 4cbcd6a
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 76 deletions.
30 changes: 0 additions & 30 deletions old/consumer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,36 +57,6 @@ where
}
}

impl<T: Copy, R: RbRef> Consumer<T, R>
where
R::Rb: RbRead<T>,
{
/// Removes first items from the ring buffer and writes them into a slice.
/// Elements must be [`Copy`].
///
/// Returns count of items been removed from the ring buffer.
pub fn pop_slice(&mut self, elems: &mut [T]) -> usize {
let (left, right) = unsafe { self.as_uninit_slices() };
let count = if elems.len() < left.len() {
unsafe { write_uninit_slice(elems, &left[..elems.len()]) };
elems.len()
} else {
let (left_elems, elems) = elems.split_at_mut(left.len());
unsafe { write_uninit_slice(left_elems, left) };
left.len()
+ if elems.len() < right.len() {
unsafe { write_uninit_slice(elems, &right[..elems.len()]) };
elems.len()
} else {
unsafe { write_uninit_slice(&mut elems[..right.len()], right) };
right.len()
}
};
unsafe { self.advance(count) };
count
}
}

/// Postponed consumer.
pub type PostponedConsumer<T, R> = Consumer<T, RbWrap<RbReadCache<T, R>>>;

Expand Down
29 changes: 28 additions & 1 deletion src/consumer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
raw::{RawBuffer, RawRb},
utils::{slice_assume_init_mut, slice_assume_init_ref},
utils::{slice_assume_init_mut, slice_assume_init_ref, write_uninit_slice},
Observer,
};
use core::{cmp, iter::Chain, iter::ExactSizeIterator, mem::MaybeUninit, ops::Deref, slice};
Expand Down Expand Up @@ -93,6 +93,33 @@ pub trait Consumer: Observer {
}
}

/// Removes items from the ring buffer and writes them into a slice.
///
/// Returns count of items been removed.
fn pop_slice(&mut self, elems: &mut [Self::Item]) -> usize
where
Self::Item: Copy,
{
let (left, right) = self.occupied_slices();
let count = if elems.len() < left.len() {
unsafe { write_uninit_slice(elems, left.get_unchecked(..elems.len())) };
elems.len()
} else {
let (left_elems, elems) = elems.split_at_mut(left.len());
unsafe { write_uninit_slice(left_elems, left) };
left.len()
+ if elems.len() < right.len() {
unsafe { write_uninit_slice(elems, right.get_unchecked(..elems.len())) };
elems.len()
} else {
unsafe { write_uninit_slice(elems.get_unchecked_mut(..right.len()), right) };
right.len()
}
};
unsafe { self.advance_read(count) };
count
}

/// Returns an iterator that removes items one by one from the ring buffer.
///
/// Iterator provides only items that are available for consumer at the moment of `pop_iter` call, it will not contain new items added after it was created.
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub mod ring_buffer;
pub mod shared;
pub mod storage;
pub mod stored;
mod transfer;
mod utils;

#[cfg(test)]
Expand All @@ -26,6 +27,7 @@ pub use observer::Observer;
pub use producer::Producer;
pub use ring_buffer::{RingBuffer, Split};
pub use shared::SharedRb;
pub use transfer::transfer;

pub mod prelude {
#[cfg(feature = "alloc")]
Expand Down
1 change: 0 additions & 1 deletion src/producer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ pub trait Producer: Observer {
}

/// Appends items from slice to the ring buffer.
/// Elements must be [`Copy`].
///
/// Returns count of items been appended to the ring buffer.
fn push_slice(&mut self, elems: &[Self::Item]) -> usize
Expand Down
1 change: 1 addition & 0 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ mod drop;
mod overwrite;
#[cfg(feature = "alloc")]
mod skip;
mod slice;
38 changes: 11 additions & 27 deletions old/tests/slice.rs → src/tests/slice.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{transfer, HeapRb, Rb};
use crate::{prelude::*, storage::Static, transfer, LocalRb};

#[test]
fn push_pop_slice() {
let buf = HeapRb::<i32>::new(4);
let (mut prod, mut cons) = buf.split();
let mut buf = LocalRb::<Static<i32, 4>>::default();
let (mut prod, mut cons) = (&mut buf).split();

let mut tmp = [0; 5];

Expand All @@ -27,10 +27,10 @@ fn push_pop_slice() {

#[test]
fn move_slice() {
let buf0 = HeapRb::<i32>::new(4);
let buf1 = HeapRb::<i32>::new(4);
let (mut prod0, mut cons0) = buf0.split();
let (mut prod1, mut cons1) = buf1.split();
let mut rb0 = LocalRb::<Static<i32, 4>>::default();
let mut rb1 = LocalRb::<Static<i32, 4>>::default();
let (mut prod0, mut cons0) = (&mut rb0).split();
let (mut prod1, mut cons1) = (&mut rb1).split();

let mut tmp = [0; 5];

Expand Down Expand Up @@ -61,10 +61,10 @@ fn move_slice() {

#[test]
fn move_slice_count() {
let buf0 = HeapRb::<i32>::new(4);
let buf1 = HeapRb::<i32>::new(4);
let (mut prod0, mut cons0) = buf0.split();
let (mut prod1, mut cons1) = buf1.split();
let mut rb0 = LocalRb::<Static<i32, 4>>::default();
let mut rb1 = LocalRb::<Static<i32, 4>>::default();
let (mut prod0, mut cons0) = (&mut rb0).split();
let (mut prod1, mut cons1) = (&mut rb1).split();

let mut tmp = [0; 5];

Expand Down Expand Up @@ -94,19 +94,3 @@ fn move_slice_count() {
assert_eq!(cons1.pop_slice(&mut tmp), 4);
assert_eq!(tmp[0..4], [6, 7, 8, 9]);
}

#[test]
#[should_panic]
fn push_slice_panic() {
let mut rb = HeapRb::<i32>::new(2);
rb.push_slice(&[1, 2, 3]);
}

#[test]
#[should_panic]
fn pop_slice_panic() {
let mut rb = HeapRb::<i32>::new(2);
rb.push(1).unwrap();
let mut tmp = [0; 2];
rb.pop_slice(&mut tmp);
}
26 changes: 9 additions & 17 deletions old/transfer.rs → src/transfer.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
use crate::{
consumer::Consumer,
producer::Producer,
ring_buffer::{RbRead, RbRef, RbWrite},
};
use crate::{consumer::Consumer, producer::Producer};

/// Moves at most `count` items from the `src` consumer to the `dst` producer.
///
/// Consumer and producer may be of different buffers as well as of the same one.
/// `count` is the number of items being moved, if `None` - as much as possible items will be moved.
///
/// Returns number of items been moved.
pub fn transfer<T, Rs: RbRef, Rd: RbRef>(
src: &mut Consumer<T, Rs>,
dst: &mut Producer<T, Rd>,
pub fn transfer<T, Rs: Consumer<Item = T>, Rd: Producer<Item = T>>(
src: &mut Rs,
dst: &mut Rd,
count: Option<usize>,
) -> usize
where
Rs::Rb: RbRead<T>,
Rd::Rb: RbWrite<T>,
{
let (src_left, src_right) = unsafe { src.as_uninit_slices() };
let (dst_left, dst_right) = unsafe { dst.free_space_as_slices() };
) -> usize {
let (src_left, src_right) = src.occupied_slices();
let (dst_left, dst_right) = dst.vacant_slices_mut();
let src_iter = src_left.iter().chain(src_right.iter());
let dst_iter = dst_left.iter_mut().chain(dst_right.iter_mut());

Expand All @@ -34,7 +26,7 @@ where
unsafe { dst_place.write(src_elem.as_ptr().read()) };
actual_count += 1;
}
unsafe { src.advance(actual_count) };
unsafe { dst.advance(actual_count) };
unsafe { src.advance_read(actual_count) };
unsafe { dst.advance_write(actual_count) };
actual_count
}

0 comments on commit 4cbcd6a

Please sign in to comment.