#[cfg(feature = "nightly-features")]
use std::{marker::Unsize, ops::CoerceUnsized};
use crate::collector::{InternalGcRef, COLLECTOR};
use crate::marker::{GcDeref, GcDrop, GcSafe};
use crate::{Finalize, Scan, Scanner, ToScan};
use std::any::{Any, TypeId};
use std::cmp::Ordering;
use std::fmt;
use std::fmt::{Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::ops::Deref;
pub struct DerefGc<T: Scan + GcDeref + ?Sized> {
backing_handle: InternalGcRef,
direct_ptr: *const T,
}
impl<T: Scan + GcDeref + ?Sized> DerefGc<T> {
pub fn new(v: T) -> Self
where
T: Sized + GcDrop,
{
let (handle, ptr) = COLLECTOR.track_with_drop(v);
Self {
backing_handle: handle,
direct_ptr: ptr,
}
}
pub fn new_no_drop(v: T) -> Self
where
T: Sized,
{
let (handle, ptr) = COLLECTOR.track_with_no_drop(v);
Self {
backing_handle: handle,
direct_ptr: ptr,
}
}
pub fn new_with_finalizer(v: T) -> Self
where
T: Sized + Finalize,
{
let (handle, ptr) = COLLECTOR.track_with_finalization(v);
Self {
backing_handle: handle,
direct_ptr: ptr,
}
}
pub fn from_box(v: Box<T>) -> Self
where
T: ToScan + GcDrop,
{
let (handle, ptr) = COLLECTOR.track_boxed_value(v);
Self {
backing_handle: handle,
direct_ptr: ptr,
}
}
}
#[allow(clippy::use_self)]
impl<T: Scan + GcDeref + ?Sized> DerefGc<T> {
#[must_use]
pub fn downcast<S>(&self) -> Option<DerefGc<S>>
where
T: Any + 'static,
S: Scan + GcDeref + Any + 'static,
{
let ptr: &T = self.deref();
if ptr.type_id() == TypeId::of::<S>() {
let new_handle = COLLECTOR.clone_handle(&self.backing_handle);
Some(DerefGc {
backing_handle: new_handle,
direct_ptr: self.direct_ptr as *const S,
})
} else {
None
}
}
}
unsafe impl<T: Scan + GcDeref + ?Sized> GcSafe for DerefGc<T> {}
unsafe impl<T: Scan + GcDeref + Send + Sync + ?Sized> GcDeref for DerefGc<T> {}
unsafe impl<T: Scan + GcDeref + ?Sized> Sync for DerefGc<T> where T: Sync + Send {}
unsafe impl<T: Scan + GcDeref + ?Sized> Send for DerefGc<T> where T: Sync + Send {}
unsafe impl<T: Scan + GcDeref + ?Sized> Scan for DerefGc<T> {
#[allow(clippy::inline_always)]
#[inline(always)]
fn scan(&self, scanner: &mut Scanner<'_>) {
scanner.add_internal_handle(self.backing_handle.clone());
}
}
impl<T: Scan + GcDeref + ?Sized> Clone for DerefGc<T> {
fn clone(&self) -> Self {
let new_handle = COLLECTOR.clone_handle(&self.backing_handle);
Self {
backing_handle: new_handle,
direct_ptr: self.direct_ptr,
}
}
}
impl<T: Scan + GcDeref + ?Sized> Deref for DerefGc<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.direct_ptr }
}
}
impl<T: Scan + GcDeref + ?Sized> Drop for DerefGc<T> {
fn drop(&mut self) {
self.backing_handle.invalidate()
}
}
unsafe impl<T: Scan + GcDeref + ?Sized> Finalize for DerefGc<T> {
unsafe fn finalize(&mut self) {
self.backing_handle.invalidate();
}
}
#[cfg(feature = "nightly-features")]
impl<T, U> CoerceUnsized<DerefGc<U>> for DerefGc<T>
where
T: Scan + GcDeref + ?Sized + Unsize<U>,
U: Scan + GcDeref + ?Sized,
{
}
impl<T: Scan + GcDeref + ?Sized> Debug for DerefGc<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("DerefGc")
.field("backing_handle", &"<SNIP>")
.field("direct_ptr", &self.direct_ptr)
.finish()
}
}
impl<T: Scan + GcDeref + ?Sized> Default for DerefGc<T>
where
T: Default + GcDrop,
{
#[must_use]
fn default() -> Self {
let v = T::default();
Self::new(v)
}
}
impl<T: Scan + GcDeref + ?Sized> Display for DerefGc<T>
where
T: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.deref().fmt(f)
}
}
impl<T: Scan + GcDeref + ?Sized> fmt::Pointer for DerefGc<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.direct_ptr, f)
}
}
impl<T: Scan + GcDeref + ?Sized> Eq for DerefGc<T> where T: Eq {}
impl<T: Scan + GcDeref + ?Sized> Hash for DerefGc<T>
where
T: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
self.deref().hash(state)
}
}
impl<T: Scan + GcDeref + ?Sized> Ord for DerefGc<T>
where
T: Ord,
{
#[must_use]
fn cmp(&self, other: &Self) -> Ordering {
(self.deref()).cmp(other.deref())
}
}
#[allow(clippy::partialeq_ne_impl)]
impl<T: Scan + GcDeref + ?Sized> PartialEq for DerefGc<T>
where
T: PartialEq,
{
#[must_use]
fn eq(&self, other: &Self) -> bool {
(self.deref()).eq(other.deref())
}
#[must_use]
fn ne(&self, other: &Self) -> bool {
(self.deref()).ne(other.deref())
}
}
impl<T: Scan + GcDeref + ?Sized> PartialOrd for DerefGc<T>
where
T: PartialOrd,
{
#[must_use]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(self.deref()).partial_cmp(other.deref())
}
#[must_use]
fn lt(&self, other: &Self) -> bool {
(self.deref()).lt(other.deref())
}
#[must_use]
fn le(&self, other: &Self) -> bool {
(self.deref()).le(other.deref())
}
#[must_use]
fn gt(&self, other: &Self) -> bool {
(self.deref()).gt(other.deref())
}
#[must_use]
fn ge(&self, other: &Self) -> bool {
(self.deref()).ge(other.deref())
}
}