use std::borrow::Cow;
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ops::Range;
use std::sync::Arc;
use crate::assume_init::AssumeInit;
pub unsafe trait Storage {
type Elem;
const MUTABLE: bool;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn as_ptr(&self) -> *const Self::Elem;
unsafe fn get(&self, offset: usize) -> Option<&Self::Elem> {
if offset < self.len() {
Some(unsafe { &*self.as_ptr().add(offset) })
} else {
None
}
}
unsafe fn get_unchecked(&self, offset: usize) -> &Self::Elem {
debug_assert!(offset < self.len());
unsafe { &*self.as_ptr().add(offset) }
}
fn slice(&self, range: Range<usize>) -> ViewData<'_, Self::Elem> {
assert_storage_range_valid(self, range.clone());
ViewData {
ptr: unsafe { self.as_ptr().add(range.start) },
len: range.len(),
_marker: PhantomData,
}
}
fn view(&self) -> ViewData<'_, Self::Elem> {
ViewData {
ptr: self.as_ptr(),
len: self.len(),
_marker: PhantomData,
}
}
unsafe fn as_slice(&self) -> &[Self::Elem] {
let (ptr, len) = (self.as_ptr(), self.len());
unsafe { std::slice::from_raw_parts(ptr, len) }
}
}
pub trait IntoStorage {
type Output: Storage;
fn into_storage(self) -> Self::Output;
}
impl<T: Storage> IntoStorage for T {
type Output = Self;
fn into_storage(self) -> Self {
self
}
}
impl<'a, T> IntoStorage for &'a [T] {
type Output = ViewData<'a, T>;
fn into_storage(self) -> ViewData<'a, T> {
ViewData {
ptr: self.as_ptr(),
len: self.len(),
_marker: PhantomData,
}
}
}
impl<'a, T, const N: usize> IntoStorage for &'a [T; N] {
type Output = ViewData<'a, T>;
fn into_storage(self) -> ViewData<'a, T> {
self.as_slice().into_storage()
}
}
impl<'a, T> IntoStorage for &'a mut [T] {
type Output = ViewMutData<'a, T>;
fn into_storage(self) -> ViewMutData<'a, T> {
ViewMutData {
ptr: self.as_mut_ptr(),
len: self.len(),
_marker: PhantomData,
}
}
}
fn assert_storage_range_valid<S: Storage + ?Sized>(storage: &S, range: Range<usize>) {
assert!(
range.start <= storage.len() && range.end <= storage.len(),
"invalid slice range {:?} for storage length {}",
range,
storage.len()
);
}
pub unsafe trait StorageMut: Storage {
fn as_mut_ptr(&mut self) -> *mut Self::Elem;
unsafe fn get_mut(&mut self, offset: usize) -> Option<&mut Self::Elem> {
if offset < self.len() {
Some(unsafe { &mut *self.as_mut_ptr().add(offset) })
} else {
None
}
}
unsafe fn get_unchecked_mut(&mut self, offset: usize) -> &mut Self::Elem {
debug_assert!(offset < self.len());
unsafe { &mut *self.as_mut_ptr().add(offset) }
}
fn slice_mut(&mut self, range: Range<usize>) -> ViewMutData<'_, Self::Elem> {
assert_storage_range_valid(self, range.clone());
ViewMutData {
ptr: unsafe { self.as_mut_ptr().add(range.start) },
len: range.len(),
_marker: PhantomData,
}
}
fn view_mut(&mut self) -> ViewMutData<'_, Self::Elem> {
ViewMutData {
ptr: self.as_mut_ptr(),
len: self.len(),
_marker: PhantomData,
}
}
unsafe fn as_slice_mut(&mut self) -> &mut [Self::Elem] {
let (ptr, len) = (self.as_mut_ptr(), self.len());
unsafe { std::slice::from_raw_parts_mut(ptr, len) }
}
}
unsafe impl<T> Storage for Vec<T> {
type Elem = T;
const MUTABLE: bool = true;
fn len(&self) -> usize {
self.len()
}
fn as_ptr(&self) -> *const T {
self.as_ptr()
}
}
unsafe impl<T> StorageMut for Vec<T> {
fn as_mut_ptr(&mut self) -> *mut T {
self.as_mut_ptr()
}
}
unsafe impl<T> Storage for Arc<Vec<T>> {
type Elem = T;
const MUTABLE: bool = true;
fn len(&self) -> usize {
self.as_ref().len()
}
fn as_ptr(&self) -> *const T {
self.as_ref().as_ptr()
}
}
#[derive(Debug)]
pub struct ViewData<'a, T> {
ptr: *const T,
len: usize,
_marker: PhantomData<&'a T>,
}
unsafe impl<T> Send for ViewData<'_, T> {}
unsafe impl<T> Sync for ViewData<'_, T> {}
impl<T> Clone for ViewData<'_, T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for ViewData<'_, T> {}
impl<'a, T> ViewData<'a, T> {
pub unsafe fn get(&self, offset: usize) -> Option<&'a T> {
if offset < self.len {
Some(unsafe { &*self.ptr.add(offset) })
} else {
None
}
}
pub unsafe fn get_unchecked(&self, offset: usize) -> &'a T {
debug_assert!(offset < self.len);
unsafe { &*self.ptr.add(offset) }
}
pub fn slice(&self, range: Range<usize>) -> ViewData<'a, T> {
assert_storage_range_valid(self, range.clone());
ViewData {
ptr: unsafe { self.as_ptr().add(range.start) },
len: range.len(),
_marker: PhantomData,
}
}
pub fn view(&self) -> ViewData<'a, T> {
*self
}
pub unsafe fn as_slice(&self) -> &'a [T] {
unsafe { std::slice::from_raw_parts(self.ptr, self.len) }
}
}
unsafe impl<T> Storage for ViewData<'_, T> {
type Elem = T;
const MUTABLE: bool = false;
fn len(&self) -> usize {
self.len
}
fn as_ptr(&self) -> *const T {
self.ptr
}
}
impl<'a, T> AssumeInit for ViewData<'a, MaybeUninit<T>> {
type Output = ViewData<'a, T>;
unsafe fn assume_init(self) -> Self::Output {
unsafe { std::mem::transmute(self) }
}
}
#[derive(Debug)]
pub struct ViewMutData<'a, T> {
ptr: *mut T,
len: usize,
_marker: PhantomData<&'a mut T>,
}
unsafe impl<T> Send for ViewMutData<'_, T> {}
impl<'a, T> ViewMutData<'a, T> {
pub unsafe fn to_slice_mut(mut self) -> &'a mut [T] {
let (ptr, len) = (self.as_mut_ptr(), self.len());
unsafe { std::slice::from_raw_parts_mut(ptr, len) }
}
pub fn split_mut(
self,
left: Range<usize>,
right: Range<usize>,
) -> (ViewMutData<'a, T>, ViewMutData<'a, T>) {
assert_storage_range_valid(&self, left.clone());
assert_storage_range_valid(&self, right.clone());
let left = ViewMutData {
ptr: unsafe { self.ptr.add(left.start) },
len: left.len(),
_marker: PhantomData,
};
let right = ViewMutData {
ptr: unsafe { self.ptr.add(right.start) },
len: right.len(),
_marker: PhantomData,
};
(left, right)
}
pub unsafe fn to_view_slice_mut(&mut self, range: Range<usize>) -> ViewMutData<'a, T> {
assert_storage_range_valid(self, range.clone());
ViewMutData {
ptr: unsafe { self.as_mut_ptr().add(range.start) },
len: range.len(),
_marker: PhantomData,
}
}
}
unsafe impl<T> Storage for ViewMutData<'_, T> {
type Elem = T;
const MUTABLE: bool = true;
fn len(&self) -> usize {
self.len
}
fn as_ptr(&self) -> *const T {
self.ptr
}
}
unsafe impl<T> StorageMut for ViewMutData<'_, T> {
fn as_mut_ptr(&mut self) -> *mut T {
self.ptr
}
}
impl<'a, T> AssumeInit for ViewMutData<'a, MaybeUninit<T>> {
type Output = ViewMutData<'a, T>;
unsafe fn assume_init(self) -> Self::Output {
unsafe { std::mem::transmute(self) }
}
}
pub enum CowData<'a, T> {
Owned(Vec<T>),
Borrowed(ViewData<'a, T>),
}
unsafe impl<T> Storage for CowData<'_, T> {
type Elem = T;
const MUTABLE: bool = false;
fn len(&self) -> usize {
match self {
CowData::Owned(vec) => vec.len(),
CowData::Borrowed(view) => view.len(),
}
}
fn as_ptr(&self) -> *const T {
match self {
CowData::Owned(vec) => vec.as_ptr(),
CowData::Borrowed(view) => view.as_ptr(),
}
}
}
impl<'a, T> IntoStorage for Cow<'a, [T]>
where
[T]: ToOwned<Owned = Vec<T>>,
{
type Output = CowData<'a, T>;
fn into_storage(self) -> Self::Output {
match self {
Cow::Owned(vec) => CowData::Owned(vec),
Cow::Borrowed(slice) => CowData::Borrowed(slice.into_storage()),
}
}
}
pub trait Alloc {
fn alloc<T>(&self, capacity: usize) -> Vec<T>;
}
impl<A: Alloc> Alloc for &A {
fn alloc<T>(&self, capacity: usize) -> Vec<T> {
A::alloc(self, capacity)
}
}
pub struct GlobalAlloc {}
impl GlobalAlloc {
pub const fn new() -> GlobalAlloc {
GlobalAlloc {}
}
}
impl Default for GlobalAlloc {
fn default() -> Self {
Self::new()
}
}
impl Alloc for GlobalAlloc {
fn alloc<T>(&self, capacity: usize) -> Vec<T> {
Vec::with_capacity(capacity)
}
}
#[cfg(test)]
mod tests {
use std::borrow::Cow;
use super::{IntoStorage, Storage, StorageMut, ViewData, ViewMutData};
fn test_storage_impl<S: Storage<Elem = i32>>(s: S, expected: &[i32]) {
assert_eq!(s.len(), expected.len());
for i in 0..s.len() {
assert_eq!(unsafe { s.get(i) }, expected.get(i));
}
assert_eq!(unsafe { s.get(s.len()) }, None);
let range = 1..s.len() - 1;
let slice = s.slice(range.clone());
assert_eq!(slice.len(), range.len());
for i in 0..slice.len() {
assert_eq!(unsafe { slice.get(i) }, expected[range.clone()].get(i));
}
assert_eq!(unsafe { s.as_slice() }, expected);
}
#[test]
fn test_storage() {
let data = &mut [1, 2, 3, 4];
let owned = data.to_vec();
test_storage_impl(owned, data);
let view: ViewData<i32> = data.as_slice().into_storage();
test_storage_impl(view, data);
let cow_view = Cow::Borrowed(data.as_slice()).into_storage();
test_storage_impl(cow_view, data);
let mut_view: ViewMutData<i32> = data.as_mut_slice().into_storage();
test_storage_impl(mut_view, &[1, 2, 3, 4]);
}
#[test]
#[should_panic(expected = "invalid slice range 5..2 for storage length 4")]
fn test_storage_slice_invalid_start() {
let data = vec![1, 2, 3, 4];
Storage::slice(&data, 5..2);
}
#[test]
#[should_panic(expected = "invalid slice range 2..5 for storage length 4")]
fn test_storage_slice_invalid_end() {
let data = vec![1, 2, 3, 4];
Storage::slice(&data, 2..5);
}
#[test]
#[should_panic(expected = "invalid slice range 5..2 for storage length 4")]
fn test_storage_slice_mut_invalid_start() {
let mut data = vec![1, 2, 3, 4];
StorageMut::slice_mut(&mut data, 5..2);
}
#[test]
#[should_panic(expected = "invalid slice range 2..5 for storage length 4")]
fn test_storage_slice_mut_invalid_end() {
let mut data = vec![1, 2, 3, 4];
StorageMut::slice_mut(&mut data, 2..5);
}
}