use std::{
fmt,
ops::{Deref, DerefMut},
};
use crate::managed::{Manager, Metrics, Pool, WeakPool};
#[must_use]
pub struct Object<M: Manager> {
pub(crate) inner: Option<ObjectInner<M>>,
pub(crate) pool: WeakPool<M>,
}
impl<M> fmt::Debug for Object<M>
where
M: fmt::Debug + Manager,
M::Type: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Object")
.field("inner", &self.inner)
.finish()
}
}
#[derive(Debug)]
pub(crate) struct ObjectInner<M: Manager> {
pub obj: M::Type,
pub id: usize,
pub metrics: Metrics,
}
impl<M: Manager> Object<M> {
#[must_use]
pub fn take(mut this: Self) -> M::Type {
let mut inner = this.inner.take().unwrap().obj;
if let Some(pool) = Object::pool(&this) {
pool.inner.detach_object(&mut inner)
}
inner
}
pub fn id(this: &Self) -> ObjectId {
ObjectId(this.inner.as_ref().unwrap().id)
}
pub fn metrics(this: &Self) -> &Metrics {
&this.inner.as_ref().unwrap().metrics
}
pub fn pool(this: &Self) -> Option<Pool<M>> {
this.pool.upgrade()
}
}
impl<M: Manager> Drop for Object<M> {
fn drop(&mut self) {
if let Some(inner) = self.inner.take() {
if let Some(pool) = self.pool.upgrade() {
pool.inner.return_object(inner)
}
}
}
}
impl<M: Manager> Deref for Object<M> {
type Target = M::Type;
fn deref(&self) -> &M::Type {
&self.inner.as_ref().unwrap().obj
}
}
impl<M: Manager> DerefMut for Object<M> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner.as_mut().unwrap().obj
}
}
impl<M: Manager> AsRef<M::Type> for Object<M> {
fn as_ref(&self) -> &M::Type {
self
}
}
impl<M: Manager> AsMut<M::Type> for Object<M> {
fn as_mut(&mut self) -> &mut M::Type {
self
}
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct ObjectId(usize);
impl fmt::Display for ObjectId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}