devela/data/dst/queue/
private.rsuse super::super::{decompose_pointer, make_fat_ptr, store_metadata};
use super::{DstBuf, DstQueue};
use crate::{MaybeUninit, Ptr};
pub(super) struct PushInnerInfo<'a, I> {
pub(super) data: &'a mut [MaybeUninit<I>],
pub(super) meta: &'a mut [MaybeUninit<I>],
pub(super) reset_slot: &'a mut usize,
pub(super) reset_value: usize,
}
impl<DST: ?Sized, BUF: DstBuf> DstQueue<DST, BUF> {
pub(super) unsafe fn push_inner(
&mut self,
fat_ptr: &DST,
) -> Result<PushInnerInfo<BUF::Inner>, ()> {
let bytes = size_of_val(fat_ptr);
let (_data_ptr, len, v) = decompose_pointer(fat_ptr);
unsafe { self.push_inner_raw(bytes, &v[..len]) }
}
pub(super) unsafe fn push_inner_raw(
&mut self,
bytes: usize,
metadata: &[usize],
) -> Result<PushInnerInfo<BUF::Inner>, ()> {
let words = BUF::round_to_words(bytes) + Self::meta_words();
if self.space_words() < words {
if self.space_words() + self.read_pos >= words {
self.compact();
}
if self.space_words() < words && self.data.extend(self.write_pos + words).is_err() {
return Err(());
}
}
assert!(self.space_words() >= words);
let slot = &mut self.data.as_mut()[self.write_pos..][..words];
let prev_write_pos = self.write_pos;
self.write_pos += words;
let (meta, rv) = slot.split_at_mut(Self::meta_words());
store_metadata(meta, metadata);
Ok(PushInnerInfo {
meta,
data: rv,
reset_slot: &mut self.write_pos,
reset_value: prev_write_pos,
})
}
#[must_use]
pub(super) fn meta_words() -> usize {
BUF::round_to_words(size_of::<&DST>() - size_of::<usize>())
}
#[must_use]
fn space_words(&self) -> usize {
self.data.as_ref().len() - self.write_pos
}
#[must_use]
pub(super) fn front_raw(&self) -> *mut DST {
assert!(self.read_pos < self.write_pos);
unsafe { self.raw_at(self.read_pos) }
}
#[must_use]
pub(super) unsafe fn raw_at(&self, pos: usize) -> *mut DST {
assert!(pos >= self.read_pos);
assert!(pos < self.write_pos);
let meta = &self.data.as_ref()[pos..];
let mw = Self::meta_words();
let (meta, data) = meta.split_at(mw);
unsafe { make_fat_ptr(data.as_ptr() as *mut (), meta) }
}
#[must_use]
pub(super) fn front_raw_mut(&mut self) -> *mut DST {
assert!(self.read_pos < self.write_pos);
unsafe { self.raw_at_mut(self.read_pos) }
}
#[must_use]
pub(super) unsafe fn raw_at_mut(&mut self, pos: usize) -> *mut DST {
assert!(pos >= self.read_pos);
assert!(pos < self.write_pos);
let meta = &mut self.data.as_mut()[pos..];
let mw = Self::meta_words();
let (meta, data) = meta.split_at_mut(mw);
unsafe { make_fat_ptr(data.as_mut_ptr() as *mut (), meta) }
}
pub(super) fn pop_front_inner(&mut self) {
unsafe {
let ptr = &mut *self.front_raw_mut();
let len = size_of_val(ptr);
Ptr::drop_in_place(ptr);
let words = BUF::round_to_words(len);
self.read_pos += Self::meta_words() + words;
}
}
}