1use core::{
2 mem::{self, MaybeUninit},
3 num::NonZeroUsize,
4 ops::Range,
5};
6
7/// Returns a pair of ranges between `head` and `tail` positions in a ring buffer with specific `capacity`.
8///
9/// `head` and `tail` may be arbitrary large, but must satisfy the following condition: `0 <= (head - tail) % (2 * capacity) <= capacity`.
10/// Actual positions are taken modulo `capacity`.
11///
12/// The first range starts from `head`. If the first slice is empty then second slice is empty too.
13pub fn ring_buffer_ranges(
14 capacity: NonZeroUsize,
15 head: usize,
16 tail: usize,
17) -> (Range<usize>, Range<usize>) {
18 let (head_quo: usize, head_rem: usize) = (head / capacity, head % capacity);
19 let (tail_quo: usize, tail_rem: usize) = (tail / capacity, tail % capacity);
20
21 if (head_quo + tail_quo) % 2 == 0 {
22 (head_rem..tail_rem, 0..0)
23 } else {
24 (head_rem..capacity.get(), 0..tail_rem)
25 }
26}
27
28// TODO: Remove on `maybe_uninit_uninit_array` stabilization.
29pub fn uninit_array<T, const N: usize>() -> [MaybeUninit<T>; N] {
30 unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() }
31}
32
33// TODO: Remove on `maybe_uninit_slice` stabilization.
34pub unsafe fn slice_assume_init_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] {
35 &*(slice as *const [MaybeUninit<T>] as *const [T])
36}
37
38// TODO: Remove on `maybe_uninit_slice` stabilization.
39pub unsafe fn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> &mut [T] {
40 &mut *(slice as *mut [MaybeUninit<T>] as *mut [T])
41}
42
43// TODO: Remove on `maybe_uninit_write_slice` stabilization.
44pub fn write_slice<'a, T: Copy>(dst: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T] {
45 let uninit_src: &[MaybeUninit<T>] = unsafe { mem::transmute(src) };
46 dst.copy_from_slice(uninit_src);
47 unsafe { slice_assume_init_mut(slice:dst) }
48}
49
50pub unsafe fn write_uninit_slice<'a, T: Copy>(
51 dst: &'a mut [T],
52 src: &[MaybeUninit<T>],
53) -> &'a mut [T] {
54 dst.copy_from_slice(src:slice_assume_init_ref(slice:src));
55 dst
56}
57