use std::fmt::{self, Debug, Formatter};
use std::hash::Hash;
use std::ops::{Deref, DerefMut};
use crate::accelerate;
pub trait Track: Surfaces {
type Call: Call;
fn call(&self, call: &Self::Call) -> u128;
fn call_mut(&mut self, call: &Self::Call);
#[inline]
fn track(&self) -> Tracked<'_, Self> {
Tracked { value: self, sink: None, id: accelerate::id() }
}
#[inline]
fn track_mut(&mut self) -> TrackedMut<'_, Self> {
TrackedMut { value: self, sink: None }
}
#[inline]
fn track_with<'a>(
&'a self,
sink: &'a dyn Sink<Call = Self::Call>,
) -> Tracked<'a, Self> {
Tracked {
value: self,
sink: Some(sink),
id: accelerate::id(),
}
}
#[inline]
fn track_mut_with<'a>(
&'a mut self,
sink: &'a dyn Sink<Call = Self::Call>,
) -> TrackedMut<'a, Self> {
TrackedMut { value: self, sink: Some(sink) }
}
}
pub trait Sink: Send + Sync {
type Call;
fn emit(&self, call: Self::Call, ret: u128) -> bool;
}
impl<S: Sink> Sink for &S {
type Call = S::Call;
fn emit(&self, call: Self::Call, ret: u128) -> bool {
(*self).emit(call, ret)
}
}
pub trait Call: Clone + PartialEq + Hash + Send + Sync {
fn is_mutable(&self) -> bool;
}
impl Call for () {
fn is_mutable(&self) -> bool {
false
}
}
pub trait Surfaces {
type Surface<'a>
where
Self: 'a;
type SurfaceMut<'a>
where
Self: 'a;
fn surface_ref<'a, 't>(tracked: &'t Tracked<'a, Self>) -> &'t Self::Surface<'a>
where
Self: Track;
fn surface_mut_ref<'a, 't>(
tracked: &'t TrackedMut<'a, Self>,
) -> &'t Self::SurfaceMut<'a>
where
Self: Track;
fn surface_mut_mut<'a, 't>(
tracked: &'t mut TrackedMut<'a, Self>,
) -> &'t mut Self::SurfaceMut<'a>
where
Self: Track;
}
pub struct Tracked<'a, T, C = <T as Track>::Call>
where
T: Track + ?Sized,
{
pub(crate) value: &'a T,
pub(crate) sink: Option<&'a dyn Sink<Call = C>>,
pub(crate) id: usize,
}
impl<'a, T> Deref for Tracked<'a, T>
where
T: Track + ?Sized,
{
type Target = T::Surface<'a>;
#[inline]
fn deref(&self) -> &Self::Target {
T::surface_ref(self)
}
}
impl<T> Debug for Tracked<'_, T>
where
T: Track + ?Sized,
{
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.pad("Tracked(..)")
}
}
impl<'a, T> Copy for Tracked<'a, T> where T: Track + ?Sized {}
impl<'a, T> Clone for Tracked<'a, T>
where
T: Track + ?Sized,
{
#[inline]
fn clone(&self) -> Self {
*self
}
}
pub struct TrackedMut<'a, T, C = <T as Track>::Call>
where
T: Track + ?Sized,
{
pub(crate) value: &'a mut T,
pub(crate) sink: Option<&'a dyn Sink<Call = C>>,
}
impl<'a, T> TrackedMut<'a, T>
where
T: Track + ?Sized,
{
#[inline]
pub fn downgrade(this: Self) -> Tracked<'a, T> {
Tracked {
value: this.value,
sink: this.sink,
id: accelerate::id(),
}
}
#[inline]
pub fn reborrow(this: &Self) -> Tracked<'_, T> {
Tracked {
value: this.value,
sink: this.sink,
id: accelerate::id(),
}
}
#[inline]
pub fn reborrow_mut(this: &mut Self) -> TrackedMut<'_, T> {
TrackedMut { value: this.value, sink: this.sink }
}
}
impl<'a, T> Deref for TrackedMut<'a, T>
where
T: Track + ?Sized,
{
type Target = T::SurfaceMut<'a>;
#[inline]
fn deref(&self) -> &Self::Target {
T::surface_mut_ref(self)
}
}
impl<'a, T> DerefMut for TrackedMut<'a, T>
where
T: Track + ?Sized,
{
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
T::surface_mut_mut(self)
}
}
impl<T> Debug for TrackedMut<'_, T>
where
T: Track + ?Sized,
{
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.pad("TrackedMut(..)")
}
}
#[inline]
pub fn to_parts_ref<T>(tracked: Tracked<'_, T>) -> (&T, Option<&dyn Sink<Call = T::Call>>)
where
T: Track + ?Sized,
{
(tracked.value, tracked.sink)
}
#[inline]
pub fn to_parts_mut_ref<'a, T>(
tracked: &'a TrackedMut<T>,
) -> (&'a T, Option<&'a dyn Sink<Call = T::Call>>)
where
T: Track + ?Sized,
{
(tracked.value, tracked.sink)
}
#[inline]
pub fn to_parts_mut_mut<'a, T>(
tracked: &'a mut TrackedMut<T>,
) -> (&'a mut T, Option<&'a dyn Sink<Call = T::Call>>)
where
T: Track + ?Sized,
{
(tracked.value, tracked.sink)
}