use crate::pointers::ISharedPointer;
use crate::service_traits::{IOwned, IShared};
use crate::Resolver;
use std::fmt;
use std::ptr::NonNull;
#[derive(Debug)]
pub(crate) struct SharedPtr {
pub ptr: NonNull<()>,
dtor: unsafe fn(NonNull<()>),
}
impl Drop for SharedPtr {
fn drop(&mut self) {
unsafe { (self.dtor)(self.ptr) }
}
}
impl SharedPtr {
pub fn new<P: ISharedPointer>(instance: P) -> Self {
SharedPtr {
ptr: unsafe { instance.into_ptr() },
dtor: P::drop_from_ptr,
}
}
}
pub(crate) type SharedCtor<S> =
fn(Resolver) -> Result<<S as IShared>::Pointer, <S as IShared>::Error>;
pub(crate) type OwnedCtor<S> = fn(
Resolver,
<S as IOwned>::Parameters,
) -> Result<<S as IOwned>::Instance, <S as IOwned>::Error>;
#[derive(Default)]
pub(crate) struct TypeErasedService {
pub shared_ptr: Option<SharedPtr>,
pub shared_ctor: Option<SharedCtor<()>>,
pub owned_ctor: Option<OwnedCtor<()>>,
}
impl fmt::Debug for TypeErasedService {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TypeErasedService")
.field("shared_ptr", &self.shared_ptr)
.field("shared_ctor", &self.shared_ctor.is_some())
.field("owned_ctor", &self.owned_ctor.is_some())
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::rc::Rc;
#[test]
fn shared_ptr_new() {
let thing = Rc::new(100);
let thing_clone = Rc::clone(&thing);
let ptr = SharedPtr::new(thing);
assert_eq!(Rc::strong_count(&thing_clone), 2);
assert_eq!(
Rc::as_ptr(&thing_clone) as *const (),
ptr.ptr.as_ptr() as *const ()
);
}
#[test]
fn shared_ptr_drop() {
let thing = Rc::new(100);
let thing_clone = Rc::clone(&thing);
let ptr = SharedPtr::new(thing);
drop(ptr);
assert_eq!(Rc::strong_count(&thing_clone), 1);
}
}