use std::ptr::NonNull;
use std::marker::PhantomData;
use allocator_api2::boxed::Box as Box2;
use allocator_api2::alloc::Allocator;
pub struct OwnPtr<'a, T: ?Sized>(NonNull<T>, PhantomData<&'a ()>);
unsafe impl<'a, T: Send + ?Sized> Send for OwnPtr<'a, T> {}
unsafe impl<'a, T: Sync + ?Sized> Sync for OwnPtr<'a, T> {}
impl<'a, T: ?Sized> OwnPtr<'a, T> {
pub unsafe fn from_ptr(ptr: *mut T) -> Self {
Self(unsafe{NonNull::new_unchecked(ptr)}, PhantomData)
}
}
impl<'a, T: ?Sized> std::ops::Deref for OwnPtr<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe{self.0.as_ref()}
}
}
impl<'a, T: ?Sized> std::ops::DerefMut for OwnPtr<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe{self.0.as_mut()}
}
}
impl<'a, T> IntoIterator for OwnPtr<'a, [T]> {
type IntoIter = IntoIter<'a, T>;
type Item = T;
fn into_iter(self) -> Self::IntoIter {
let ret_val = IntoIter{
start: self.0.cast::<T>(),
end: unsafe{self.0.cast::<T>().add(self.0.len())},
marker: PhantomData
};
std::mem::forget(self);
ret_val
}
}
impl<'a, T: ?Sized> Drop for OwnPtr<'a, T> {
fn drop (&mut self) {
unsafe{std::ptr::drop_in_place(self.0.as_ptr())};
}
}
impl<'a, T: ?Sized, A: Allocator + 'a> From<Box2<T, A>> for OwnPtr<'a, T> {
fn from(other: Box2<T, A>) -> Self {
unsafe{Self::from_ptr(Box2::into_raw(other))}
}
}
impl<'a, T: ?Sized> From<Box<T>> for OwnPtr<'a, T> {
fn from(other: Box<T>) -> Self {
unsafe{Self::from_ptr(Box::into_raw(other))}
}
}
pub struct IntoIter<'a, T>{
start: NonNull<T>,
end: NonNull<T>,
marker: PhantomData<&'a ()>
}
impl<'a, T> Iterator for IntoIter<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.nth(0)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
if (unsafe{self.end.offset_from(self.start)} as usize) <= n {
unsafe{std::ptr::drop_in_place(std::ptr::slice_from_raw_parts_mut(self.start.as_ptr(), self.len()))};
self.start = self.end;
None
} else {
unsafe{std::ptr::drop_in_place(std::ptr::slice_from_raw_parts_mut(self.start.as_ptr(), n))};
self.start = unsafe{self.start.add(n + 1)};
Some(unsafe{self.start.sub(1).read()})
}
}
fn last(mut self) -> Option<Self::Item> {
if self.start == self.end {
None
} else {
self.nth(self.len() - 1)
}
}
fn count(self) -> usize {
self.len()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl<'a, T> DoubleEndedIterator for IntoIter<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.nth_back(0)
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
if (unsafe{self.end.offset_from(self.start)} as usize) <= n {
unsafe{std::ptr::drop_in_place(std::ptr::slice_from_raw_parts_mut(self.start.as_ptr(), self.len()))};
self.end = self.start;
None
} else {
unsafe{std::ptr::drop_in_place(std::ptr::slice_from_raw_parts_mut(self.end.sub(n).as_ptr(), n))};
self.end = unsafe{self.end.sub(n)};
Some(unsafe{self.end.sub(1).read()})
}
}
}
impl<'a, T> Drop for IntoIter<'a, T> {
fn drop (&mut self) {
unsafe{std::ptr::drop_in_place(std::ptr::slice_from_raw_parts_mut(self.start.as_ptr(), self.len()))}
}
}
impl<'a, T> ExactSizeIterator for IntoIter<'a, T> {
fn len(&self) -> usize {
unsafe{self.end.offset_from(self.start) as usize}
}
}