#[cfg(feature = "nightly")]
use alloc::alloc::{Allocator, Global};
use core::mem::ManuallyDrop;
use core::ptr;
#[cfg(not(feature = "nightly"))]
use crate::allocator::{Allocator, Global};
use crate::array::Array;
use crate::dim::Const;
use crate::index::Axis;
use crate::mapping::Mapping;
use crate::shape::{ConstShape, Shape};
use crate::slice::Slice;
use crate::tensor::Tensor;
use crate::view::ViewMut;
pub trait Buffer {
type Item;
type Shape: Shape;
#[doc(hidden)]
fn as_mut_slice(&mut self) -> &mut Slice<ManuallyDrop<Self::Item>, Self::Shape>;
#[doc(hidden)]
fn as_slice(&self) -> &Slice<ManuallyDrop<Self::Item>, Self::Shape>;
}
pub struct Drain<'a, T, S: Shape, A: Allocator = Global> {
tensor: &'a mut Tensor<T, S, A>,
view: ViewMut<'a, ManuallyDrop<T>, S>,
new_size: usize,
tail: usize,
}
impl<'a, T, S: Shape, A: Allocator> Drain<'a, T, S, A> {
#[inline]
pub(crate) fn new(tensor: &'a mut Tensor<T, S, A>, start: usize, end: usize) -> Self {
assert!(start <= end && end <= tensor.dim(0), "invalid range");
let new_size = tensor.dim(0) - (end - start);
let tail = Axis::resize(Const::<0>, tensor.mapping(), new_size - start).len();
unsafe {
tensor.set_mapping(Mapping::resize_dim(tensor.mapping(), 0, start));
}
let ptr = unsafe { tensor.as_mut_ptr().add(tensor.len()) as *mut ManuallyDrop<T> };
let mapping = Mapping::resize_dim(tensor.mapping(), 0, end - start);
let view = unsafe { ViewMut::new_unchecked(ptr, mapping) };
Self { tensor, view, new_size, tail }
}
}
impl<T, S: Shape, A: Allocator> Buffer for Drain<'_, T, S, A> {
type Item = T;
type Shape = S;
#[inline]
fn as_mut_slice(&mut self) -> &mut Slice<ManuallyDrop<T>, S> {
&mut self.view
}
#[inline]
fn as_slice(&self) -> &Slice<ManuallyDrop<T>, S> {
&self.view
}
}
impl<T, S: Shape, A: Allocator> Drop for Drain<'_, T, S, A> {
#[inline]
fn drop(&mut self) {
let mapping = Mapping::resize_dim(self.tensor.mapping(), 0, self.new_size);
unsafe {
ptr::copy(self.view.as_ptr().add(self.view.len()), self.view.as_mut_ptr(), self.tail);
self.tensor.set_mapping(mapping);
}
}
}
impl<T, S: ConstShape> Buffer for Array<ManuallyDrop<T>, S> {
type Item = T;
type Shape = S;
#[inline]
fn as_mut_slice(&mut self) -> &mut Slice<ManuallyDrop<T>, S> {
self
}
#[inline]
fn as_slice(&self) -> &Slice<ManuallyDrop<T>, S> {
self
}
}
impl<T, S: Shape, A: Allocator> Buffer for Tensor<ManuallyDrop<T>, S, A> {
type Item = T;
type Shape = S;
#[inline]
fn as_mut_slice(&mut self) -> &mut Slice<ManuallyDrop<T>, S> {
self
}
#[inline]
fn as_slice(&self) -> &Slice<ManuallyDrop<T>, S> {
self
}
}