use crate::pointer::Pointer;
use crate::pool::Pool;
use crate::refbox::assume_init;
use crate::refbox::data_ptr;
use crate::refbox::RefBox;
use crate::PoolClone;
use crate::{types::ElementPointer, PoolDefault};
use std::borrow::Borrow;
use std::borrow::BorrowMut;
use std::cmp::Ordering;
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Error;
use std::fmt::Formatter;
use std::hash::Hash;
use std::hash::Hasher;
use std::ops::DerefMut;
use std::ptr::NonNull;
use std::{ops::Deref, pin::Pin};
pub struct PoolBox<A> {
pub(crate) handle: ElementPointer<A>,
}
impl<A> PoolBox<A> {
pub fn default(pool: &Pool<A>) -> Self
where
A: PoolDefault,
{
let mut handle = pool.pop();
unsafe {
PoolDefault::default_uninit(data_ptr(&mut handle));
assume_init(handle)
}
.into_box()
}
pub fn new(pool: &Pool<A>, value: A) -> Self {
let mut handle = pool.pop();
unsafe {
data_ptr(&mut handle).as_mut_ptr().write(value);
assume_init(handle)
}
.into_box()
}
pub fn clone_from(pool: &Pool<A>, value: &A) -> Self
where
A: PoolClone,
{
let mut handle = pool.pop();
unsafe {
value.clone_uninit(data_ptr(&mut handle));
assume_init(handle)
}
.into_box()
}
pub fn pin_default(pool: &Pool<A>) -> Pin<Self>
where
A: PoolDefault,
{
unsafe { Pin::new_unchecked(Self::default(pool)) }
}
pub fn pin(pool: &Pool<A>, value: A) -> Pin<Self> {
unsafe { Pin::new_unchecked(Self::new(pool, value)) }
}
pub fn ptr_eq(left: &Self, right: &Self) -> bool {
std::ptr::eq(left.handle.get_ptr(), right.handle.get_ptr())
}
pub fn into_raw_non_null(b: PoolBox<A>) -> NonNull<A> {
let ptr = b.handle.cast();
std::mem::forget(b);
ptr
}
pub fn into_raw(b: PoolBox<A>) -> *mut A {
Self::into_raw_non_null(b).as_ptr()
}
pub unsafe fn from_raw(ptr: *mut A) -> Self {
Self {
handle: ElementPointer::wrap(ptr.cast()),
}
}
fn box_ref(&self) -> &RefBox<A> {
unsafe { &*self.handle.get_ptr() }
}
fn box_ref_mut(&mut self) -> &mut RefBox<A> {
unsafe { &mut *self.handle.get_ptr() }
}
}
impl<A> Drop for PoolBox<A> {
fn drop(&mut self) {
let handle = unsafe { Box::from_raw(self.handle.get_ptr()) };
handle.return_to_pool();
}
}
impl<A> Clone for PoolBox<A>
where
A: PoolClone,
{
fn clone(&self) -> Self {
let mut handle = self.box_ref().pool.pop();
unsafe {
self.deref().clone_uninit(data_ptr(&mut handle));
assume_init(handle)
}
.into_box()
}
}
impl<A> Deref for PoolBox<A> {
type Target = A;
fn deref(&self) -> &Self::Target {
self.box_ref().value_as_ref()
}
}
impl<A> DerefMut for PoolBox<A> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.box_ref_mut().value_as_mut()
}
}
impl<A> AsRef<A> for PoolBox<A> {
fn as_ref(&self) -> &A {
self.deref()
}
}
impl<A> AsMut<A> for PoolBox<A> {
fn as_mut(&mut self) -> &mut A {
self.deref_mut()
}
}
impl<A> Borrow<A> for PoolBox<A> {
fn borrow(&self) -> &A {
self.deref()
}
}
impl<A> BorrowMut<A> for PoolBox<A> {
fn borrow_mut(&mut self) -> &mut A {
self.deref_mut()
}
}
impl<A> PartialEq for PoolBox<A>
where
A: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
(**self) == (**other)
}
}
impl<A> Eq for PoolBox<A> where A: Eq {}
impl<A> PartialOrd for PoolBox<A>
where
A: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
}
impl<A> Ord for PoolBox<A>
where
A: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
(**self).cmp(&**other)
}
}
impl<A> Hash for PoolBox<A>
where
A: Hash,
{
fn hash<H: Hasher>(&self, hasher: &mut H) {
(**self).hash(hasher)
}
}
impl<A> Display for PoolBox<A>
where
A: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
(**self).fmt(f)
}
}
impl<A> Debug for PoolBox<A>
where
A: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
(**self).fmt(f)
}
}
impl<A> std::fmt::Pointer for PoolBox<A> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
std::fmt::Pointer::fmt(&(&**self as *const A), f)
}
}