use core::{mem, slice};
use crate::spi::{BinData, UnsafeBin};
use crate::{Bin, DefaultExcessShrink, RcCounter, RcDecResult, RcMeta, RcUtils};
#[repr(C)]
pub struct RcData<TCounter: RcCounter> {
pub data_ptr: *const u8,
pub data_len: usize,
pub meta_ptr: *const RcMeta<TCounter>,
}
impl<TCounter: RcCounter> RcData<TCounter> {
#[inline]
pub unsafe fn from_bin(bin: &Bin) -> &Self {
let bin_data = bin._data() as *const BinData;
let self_data = bin_data as *const Self;
&*self_data
}
#[allow(clippy::mut_from_ref)]
#[inline]
pub unsafe fn from_bin_mut_cast(bin: &Bin) -> &mut Self {
let bin_data = bin._data() as *const BinData as *mut BinData;
let self_data = bin_data as *mut Self;
&mut *self_data
}
#[inline]
pub unsafe fn from_bin_mut(bin: &mut Bin) -> &mut Self {
let bin_data = bin._data_mut() as *mut BinData;
let self_data = bin_data as *mut Self;
&mut *self_data
}
#[inline]
pub unsafe fn to_bin_data(&self) -> BinData {
mem::transmute_copy::<Self, BinData>(self)
}
#[inline]
pub unsafe fn into_bin_data(self) -> BinData {
mem::transmute::<Self, BinData>(self)
}
}
impl<TCounter: RcCounter> RcData<TCounter> {
#[inline]
pub(crate) unsafe fn new_from_vec_raw(mut vec: Vec<u8>) -> Self {
let meta = RcMeta::<TCounter>::initial(TCounter::new());
let meta = RcUtils::add_padding_and_metadata(&mut vec, meta);
let meta_mut = meta as *mut RcMeta<TCounter>;
(*meta_mut).capacity = vec.capacity();
(*meta_mut).vec_ptr = vec.as_ptr();
let this = Self {
data_ptr: vec.as_ptr(),
data_len: vec.len(),
meta_ptr: meta,
};
mem::forget(vec);
this
}
#[inline]
fn rc_meta(&self) -> &RcMeta<TCounter> {
let meta_ptr = self.meta_ptr;
unsafe { &*meta_ptr }
}
#[inline]
fn rc_meta_mut(&mut self) -> &mut RcMeta<TCounter> {
let meta_ptr = self.meta_ptr as *mut RcMeta<TCounter>;
unsafe { &mut *meta_ptr }
}
#[inline]
pub(crate) fn drop(&mut self) {
let meta = self.rc_meta_mut();
let dec_result = meta.counter.decrement();
match dec_result {
RcDecResult::Zero => {
unsafe { meta.extract_vec(0) };
}
RcDecResult::More => {
}
}
}
#[inline]
pub(crate) fn clone(&mut self) -> Self {
self.rc_meta_mut().counter.increment();
Self {
data_ptr: self.data_ptr,
meta_ptr: self.meta_ptr,
data_len: self.data_len,
}
}
#[inline]
pub(crate) fn as_slice(&self) -> &[u8] {
let ptr = self.data_ptr;
let len = self.data_len;
unsafe { slice::from_raw_parts(ptr, len) }
}
#[inline]
pub(crate) fn is_empty(&self) -> bool {
self.data_len == 0
}
#[inline]
pub(crate) fn mut_self_into_vec(&mut self) -> Vec<u8> {
let dec_result = {
let meta = self.rc_meta_mut();
meta.counter.decrement()
};
match dec_result {
RcDecResult::Zero => {
let meta = self.rc_meta();
if self.data_ptr == meta.vec_ptr {
let mut vec = unsafe { meta.extract_vec(self.data_len) };
RcUtils::maybe_shrink_vec::<TCounter, DefaultExcessShrink>(&mut vec);
vec
} else {
let vec = unsafe { meta.extract_vec(self.data_len) };
let new_vec =
RcUtils::slice_to_vec_with_meta_overhead::<TCounter>(vec.as_slice());
new_vec
}
}
RcDecResult::More => {
let slice = self.as_slice();
RcUtils::slice_to_vec_with_meta_overhead::<TCounter>(slice)
}
}
}
#[inline]
pub(crate) fn slice(&mut self, start: usize, end_excluded: usize) -> Option<Self> {
if self.as_slice().get(start..end_excluded).is_some() {
let mut clone = self.clone();
unsafe {
clone.data_ptr = clone.data_ptr.add(start);
}
clone.data_len = end_excluded - start;
Some(clone)
} else {
None
}
}
}