use std::iter::FromIterator;
use std::ptr::NonNull;
use std::usize;
use crate::trusted_len::TrustedLen;
use crate::types::{BitChunk, NativeType};
use super::bytes::{Bytes, Deallocation};
#[cfg(feature = "cache_aligned")]
use crate::vec::AlignedVec as Vec;
use super::immutable::Buffer;
pub struct MutableBuffer<T: NativeType> {
data: Vec<T>,
}
#[cfg(not(feature = "cache_aligned"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "cache_aligned"))))]
impl<T: NativeType> From<MutableBuffer<T>> for Vec<T> {
fn from(data: MutableBuffer<T>) -> Self {
data.data
}
}
impl<T: NativeType> std::fmt::Debug for MutableBuffer<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&**self, f)
}
}
impl<T: NativeType> PartialEq for MutableBuffer<T> {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T: NativeType> MutableBuffer<T> {
#[inline]
pub fn new() -> Self {
Self { data: Vec::new() }
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self {
data: Vec::with_capacity(capacity),
}
}
#[cfg(not(feature = "cache_aligned"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "cache_aligned"))))]
#[inline]
pub fn from_vec(data: Vec<T>) -> Self {
Self { data }
}
#[inline]
pub fn from_len_zeroed(len: usize) -> Self {
#[cfg(not(feature = "cache_aligned"))]
let data = vec![T::default(); len];
#[cfg(feature = "cache_aligned")]
let data = Vec::from_len_zeroed(len);
Self { data }
}
#[inline(always)]
pub fn reserve(&mut self, additional: usize) {
self.data.reserve(additional)
}
#[inline(always)]
pub fn resize(&mut self, new_len: usize, value: T) {
self.data.resize(new_len, value)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.data.len()
}
#[inline]
pub fn capacity(&self) -> usize {
self.data.capacity()
}
#[inline]
pub fn clear(&mut self) {
self.data.clear()
}
#[inline]
pub fn truncate(&mut self, len: usize) {
self.data.truncate(len)
}
#[inline]
pub fn as_slice(&self) -> &[T] {
self.data.as_slice()
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
self.data.as_mut_slice()
}
#[inline]
pub fn as_ptr(&self) -> *const T {
self.data.as_ptr()
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
self.data.as_mut_ptr()
}
#[inline]
pub fn extend_from_slice(&mut self, items: &[T]) {
self.data.extend_from_slice(items)
}
#[inline]
pub fn push(&mut self, item: T) {
self.data.push(item)
}
#[inline]
pub(crate) unsafe fn push_unchecked(&mut self, item: T) {
let dst = self.as_mut_ptr().add(self.len());
std::ptr::write(dst, item);
self.data.set_len(self.data.len() + 1);
}
#[inline]
pub unsafe fn set_len(&mut self, len: usize) {
debug_assert!(len <= self.capacity());
self.data.set_len(len);
}
#[inline]
pub fn extend_constant(&mut self, additional: usize, value: T) {
self.resize(self.len() + additional, value)
}
pub fn shrink_to_fit(&mut self) {
self.data.shrink_to_fit();
}
}
impl<A: NativeType> Extend<A> for MutableBuffer<A> {
fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
self.data.extend(iter)
}
}
impl<T: NativeType> MutableBuffer<T> {
#[inline]
pub fn extend_from_trusted_len_iter<I: TrustedLen<Item = T>>(&mut self, iterator: I) {
unsafe { self.extend_from_trusted_len_iter_unchecked(iterator) }
}
#[inline]
pub unsafe fn extend_from_trusted_len_iter_unchecked<I: Iterator<Item = T>>(
&mut self,
iterator: I,
) {
let (_, upper) = iterator.size_hint();
let upper = upper.expect("trusted_len_iter requires an upper limit");
let len = upper;
let self_len = self.len();
self.reserve(len);
let mut dst = self.as_mut_ptr().add(self_len);
for item in iterator {
std::ptr::write(dst, item);
dst = dst.add(1);
}
assert_eq!(
dst.offset_from(self.as_ptr().add(self_len)) as usize,
upper,
"Trusted iterator length was not accurately reported"
);
self.set_len(self_len + len);
}
#[inline]
pub fn from_trusted_len_iter<I: Iterator<Item = T> + TrustedLen>(iterator: I) -> Self {
let mut buffer = MutableBuffer::new();
buffer.extend_from_trusted_len_iter(iterator);
buffer
}
#[inline]
pub unsafe fn from_trusted_len_iter_unchecked<I: Iterator<Item = T>>(iterator: I) -> Self {
let mut buffer = MutableBuffer::new();
buffer.extend_from_trusted_len_iter_unchecked(iterator);
buffer
}
#[inline]
pub fn try_from_trusted_len_iter<E, I: TrustedLen<Item = std::result::Result<T, E>>>(
iterator: I,
) -> std::result::Result<Self, E> {
unsafe { Self::try_from_trusted_len_iter_unchecked(iterator) }
}
#[inline]
pub unsafe fn try_from_trusted_len_iter_unchecked<
E,
I: Iterator<Item = std::result::Result<T, E>>,
>(
iterator: I,
) -> std::result::Result<Self, E> {
let (_, upper) = iterator.size_hint();
let upper = upper.expect("try_from_trusted_len_iter requires an upper limit");
let len = upper;
let mut buffer = MutableBuffer::with_capacity(len);
let mut dst = buffer.as_mut_ptr();
for item in iterator {
std::ptr::write(dst, item?);
dst = dst.add(1);
}
assert_eq!(
dst.offset_from(buffer.as_ptr()) as usize,
upper,
"Trusted iterator length was not accurately reported"
);
buffer.set_len(len);
Ok(buffer)
}
}
impl<T: NativeType> FromIterator<T> for MutableBuffer<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let data = Vec::from_iter(iter);
Self { data }
}
}
impl<T: NativeType> Default for MutableBuffer<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: NativeType> std::ops::Deref for MutableBuffer<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
&self.data
}
}
impl<T: NativeType> std::ops::DerefMut for MutableBuffer<T> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
&mut self.data
}
}
impl<T: NativeType, P: AsRef<[T]>> From<P> for MutableBuffer<T> {
#[inline]
fn from(slice: P) -> Self {
let mut buffer = MutableBuffer::new();
buffer.extend_from_slice(slice.as_ref());
buffer
}
}
impl<T: NativeType> From<MutableBuffer<T>> for Buffer<T> {
#[inline]
fn from(buffer: MutableBuffer<T>) -> Self {
Self::from_bytes(buffer.into())
}
}
impl<T: NativeType> From<MutableBuffer<T>> for Bytes<T> {
#[inline]
fn from(buffer: MutableBuffer<T>) -> Self {
let mut data = buffer.data;
let ptr = NonNull::new(data.as_mut_ptr()).unwrap();
let len = data.len();
let capacity = data.capacity();
let result = unsafe { Bytes::new(ptr, len, Deallocation::Native(capacity)) };
std::mem::forget(data);
result
}
}
impl MutableBuffer<u8> {
#[inline]
pub fn from_chunk_iter<T: BitChunk, I: TrustedLen<Item = T>>(iter: I) -> Self {
unsafe { Self::from_chunk_iter_unchecked(iter) }
}
#[inline]
pub unsafe fn from_chunk_iter_unchecked<T: BitChunk, I: Iterator<Item = T>>(
iterator: I,
) -> Self {
let (_, upper) = iterator.size_hint();
let upper = upper.expect("try_from_trusted_len_iter requires an upper limit");
let len = upper * std::mem::size_of::<T>();
let mut buffer = MutableBuffer::with_capacity(len);
let mut dst = buffer.as_mut_ptr();
for item in iterator {
let bytes = item.to_ne_bytes();
for i in 0..std::mem::size_of::<T>() {
std::ptr::write(dst, bytes[i]);
dst = dst.add(1);
}
}
assert_eq!(
dst.offset_from(buffer.as_ptr()) as usize,
len,
"Trusted iterator length was not accurately reported"
);
buffer.set_len(len);
buffer
}
}
unsafe impl<T: NativeType> Send for MutableBuffer<T> {}
unsafe impl<T: NativeType> Sync for MutableBuffer<T> {}