use std::fmt::Debug;
use std::ops::{Deref, DerefMut};
use crate::general::Snapshot;
use crate::helper::{AsDeref, AsDerefMut, QuasiObserver, Succ, Unsigned};
use crate::observe::{Observer, RefObserve, RefObserver, SerializeObserver};
use crate::{Mutations, Observe};
pub struct DerefObserver<O> {
inner: O,
}
pub struct DerefMutObserver<O> {
inner: O,
}
impl<O> Deref for DerefObserver<O> {
type Target = O;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<O> Deref for DerefMutObserver<O> {
type Target = O;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<O> DerefMut for DerefObserver<O> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<O> DerefMut for DerefMutObserver<O> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<O, D> QuasiObserver for DerefObserver<O>
where
D: Unsigned,
O: QuasiObserver<InnerDepth = Succ<D>>,
O::Head: AsDeref<D>,
{
type Head = O::Head;
type OuterDepth = Succ<O::OuterDepth>;
type InnerDepth = D;
fn invalidate(this: &mut Self) {
O::invalidate(&mut this.inner);
}
}
impl<O, D> QuasiObserver for DerefMutObserver<O>
where
D: Unsigned,
O: QuasiObserver<InnerDepth = Succ<D>>,
O::Head: AsDeref<D>,
{
type Head = O::Head;
type OuterDepth = Succ<O::OuterDepth>;
type InnerDepth = D;
fn invalidate(this: &mut Self) {
O::invalidate(&mut this.inner);
}
}
impl<O, D> Observer for DerefObserver<O>
where
O: RefObserver<InnerDepth = Succ<D>>,
O::Head: AsDeref<D>,
D: Unsigned,
{
fn observe(head: &mut Self::Head) -> Self {
Self {
inner: O::observe(head),
}
}
unsafe fn relocate(this: &mut Self, head: &mut Self::Head) {
unsafe { O::relocate(&mut this.inner, head) }
}
}
impl<O, D> RefObserver for DerefObserver<O>
where
O: RefObserver<InnerDepth = Succ<D>>,
O::Head: AsDeref<D>,
D: Unsigned,
{
fn observe(head: &Self::Head) -> Self {
Self {
inner: O::observe(head),
}
}
unsafe fn relocate(this: &mut Self, head: &Self::Head) {
unsafe { O::relocate(&mut this.inner, head) }
}
}
impl<O, D> Observer for DerefMutObserver<O>
where
O: Observer<InnerDepth = Succ<D>>,
O::Head: AsDeref<D>,
D: Unsigned,
{
fn observe(head: &mut Self::Head) -> Self {
Self {
inner: O::observe(head),
}
}
unsafe fn relocate(this: &mut Self, head: &mut Self::Head) {
unsafe { O::relocate(&mut this.inner, head) }
}
}
impl<O, D> SerializeObserver for DerefObserver<O>
where
O: SerializeObserver<InnerDepth = Succ<D>>,
O::Head: AsDeref<D>,
D: Unsigned,
{
unsafe fn flush(this: &mut Self) -> Mutations {
unsafe { O::flush(&mut this.inner) }
}
unsafe fn flat_flush(this: &mut Self) -> Mutations {
unsafe { O::flat_flush(&mut this.inner) }
}
}
impl<O, D> SerializeObserver for DerefMutObserver<O>
where
O: SerializeObserver<InnerDepth = Succ<D>>,
O::Head: AsDeref<D>,
D: Unsigned,
{
unsafe fn flush(this: &mut Self) -> Mutations {
unsafe { O::flush(&mut this.inner) }
}
unsafe fn flat_flush(this: &mut Self) -> Mutations {
unsafe { O::flat_flush(&mut this.inner) }
}
}
macro_rules! impl_fmt {
($($trait:ident),* $(,)?) => {
$(
impl<O> std::fmt::$trait for DerefObserver<O>
where
O: std::fmt::$trait,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::$trait::fmt(&self.inner, f)
}
}
impl<O> std::fmt::$trait for DerefMutObserver<O>
where
O: std::fmt::$trait,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::$trait::fmt(&self.inner, f)
}
}
)*
};
}
impl_fmt! {
Binary,
Display,
LowerExp,
LowerHex,
Octal,
Pointer,
UpperExp,
UpperHex,
}
impl<O> Debug for DerefObserver<O>
where
O: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("DerefObserver").field(&self.inner).finish()
}
}
impl<O> Debug for DerefMutObserver<O>
where
O: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("DerefObserver").field(&self.inner).finish()
}
}
impl<O1, O2> PartialEq<DerefObserver<O2>> for DerefObserver<O1>
where
O1: PartialEq<O2>,
{
fn eq(&self, other: &DerefObserver<O2>) -> bool {
self.inner.eq(&other.inner)
}
}
impl<O1, O2> PartialEq<DerefMutObserver<O2>> for DerefMutObserver<O1>
where
O1: PartialEq<O2>,
{
fn eq(&self, other: &DerefMutObserver<O2>) -> bool {
self.inner.eq(&other.inner)
}
}
impl<O> Eq for DerefObserver<O> where O: Eq {}
impl<O> Eq for DerefMutObserver<O> where O: Eq {}
impl<O1, O2> PartialOrd<DerefObserver<O2>> for DerefObserver<O1>
where
O1: PartialOrd<O2>,
{
fn partial_cmp(&self, other: &DerefObserver<O2>) -> Option<std::cmp::Ordering> {
self.inner.partial_cmp(&other.inner)
}
}
impl<O1, O2> PartialOrd<DerefMutObserver<O2>> for DerefMutObserver<O1>
where
O1: PartialOrd<O2>,
{
fn partial_cmp(&self, other: &DerefMutObserver<O2>) -> Option<std::cmp::Ordering> {
self.inner.partial_cmp(&other.inner)
}
}
impl<O> Ord for DerefObserver<O>
where
O: Ord,
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.inner.cmp(&other.inner)
}
}
impl<O> Ord for DerefMutObserver<O>
where
O: Ord,
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.inner.cmp(&other.inner)
}
}
macro_rules! impl_deref_observe {
($(impl $([$($gen:tt)*])? Observe for $ty:ty as $ob:ident $(where { $($where:tt)+ })?;)*) => {
$(
impl <$($($gen)*)?> Observe for $ty {
type Observer<'ob, S, D>
= $ob<T::Observer<'ob, S, Succ<D>>>
where
Self: 'ob,
D: Unsigned,
S: AsDerefMut<D, Target = Self> + ?Sized + 'ob;
type Spec = T::Spec;
}
)*
};
}
impl_deref_observe! {
impl [T: Observe + ?Sized] Observe for Box<T> as DerefMutObserver;
impl [T: Observe + ?Sized] Observe for &mut T as DerefMutObserver;
impl [T: RefObserve + ?Sized] Observe for &T as DerefObserver;
impl [T: RefObserve + ?Sized] Observe for std::rc::Rc<T> as DerefObserver;
impl [T: RefObserve + ?Sized] Observe for std::sync::Arc<T> as DerefObserver;
}
macro_rules! impl_deref_ref_observe {
($(impl $([$($gen:tt)*])? RefObserve for $ty:ty $(where { $($where:tt)+ })?;)*) => {
$(
impl <$($($gen)*)?> RefObserve for $ty {
type Observer<'ob, S, D>
= DerefObserver<T::Observer<'ob, S, Succ<D>>>
where
Self: 'ob,
D: Unsigned,
S: AsDeref<D, Target = Self> + ?Sized + 'ob;
type Spec = T::Spec;
}
)*
};
}
impl_deref_ref_observe! {
impl [T: RefObserve + ?Sized] RefObserve for &T;
impl [T: RefObserve + ?Sized] RefObserve for &mut T;
impl [T: RefObserve + ?Sized] RefObserve for Box<T>;
impl [T: RefObserve + ?Sized] RefObserve for std::rc::Rc<T>;
impl [T: RefObserve + ?Sized] RefObserve for std::sync::Arc<T>;
}
macro_rules! impl_snapshot {
($(impl $([$($gen:tt)*])? Snapshot for $ty:ty as $value:ty $(where { $($where:tt)+ })?;)*) => {
$(
impl <$($($gen)*)?> Snapshot for $ty {
type Snapshot = $value;
fn to_snapshot(&self) -> Self::Snapshot {
(**self).to_snapshot()
}
fn eq_snapshot(&self, snapshot: &Self::Snapshot) -> bool {
(**self).eq_snapshot(snapshot)
}
}
)*
};
}
impl_snapshot! {
impl [T: Snapshot + ?Sized] Snapshot for &T as T::Snapshot;
impl [T: Snapshot + ?Sized] Snapshot for &mut T as T::Snapshot;
impl [T: Snapshot + ?Sized] Snapshot for Box<T> as T::Snapshot;
impl [T: Snapshot + ?Sized] Snapshot for std::rc::Rc<T> as T::Snapshot;
impl [T: Snapshot + ?Sized] Snapshot for std::sync::Arc<T> as T::Snapshot;
}
macro_rules! generic_impl_cmp {
($(impl $([$($gen:tt)*])? _ for $ty:ty);* $(;)?) => {
$(
impl<$($($gen)*,)? O, D, T: ?Sized> PartialEq<$ty> for DerefObserver<O>
where
O: QuasiObserver<InnerDepth = Succ<D>>,
O::Head: AsDeref<D, Target = T>,
T: PartialEq<$ty>,
D: Unsigned,
{
fn eq(&self, other: &$ty) -> bool {
self.untracked_ref().eq(other)
}
}
impl<$($($gen)*,)? O, D, T: ?Sized> PartialEq<$ty> for DerefMutObserver<O>
where
O: QuasiObserver<InnerDepth = Succ<D>>,
O::Head: AsDeref<D, Target = T>,
T: PartialEq<$ty>,
D: Unsigned,
{
fn eq(&self, other: &$ty) -> bool {
self.untracked_ref().eq(other)
}
}
impl<$($($gen)*,)? O, D, T: ?Sized> PartialOrd<$ty> for DerefObserver<O>
where
O: QuasiObserver<InnerDepth = Succ<D>>,
O::Head: AsDeref<D, Target = T>,
T: PartialOrd<$ty>,
D: Unsigned,
{
fn partial_cmp(&self, other: &$ty) -> Option<std::cmp::Ordering> {
self.untracked_ref().partial_cmp(other)
}
}
impl<$($($gen)*,)? O, D, T: ?Sized> PartialOrd<$ty> for DerefMutObserver<O>
where
O: QuasiObserver<InnerDepth = Succ<D>>,
O::Head: AsDeref<D, Target = T>,
T: PartialOrd<$ty>,
D: Unsigned,
{
fn partial_cmp(&self, other: &$ty) -> Option<std::cmp::Ordering> {
self.untracked_ref().partial_cmp(other)
}
}
)*
};
}
generic_impl_cmp! {
impl [U: ?Sized] _ for Box<U>;
impl ['a, U: ?Sized] _ for &'a U;
impl ['a, U: ?Sized] _ for &'a mut U;
impl [U: ?Sized] _ for std::rc::Rc<U>;
impl [U: ?Sized] _ for std::sync::Arc<U>;
}
#[cfg(test)]
mod test {
use morphix_test_utils::*;
use serde_json::json;
use crate::adapter::Json;
use crate::observe::{ObserveExt, SerializeObserverExt};
#[test]
fn test_deref_method() {
let mut value = Box::new(String::from("Hello, World!"));
let mut ob = value.__observe();
assert_eq!(*ob, "Hello, World!");
ob.push_str("\n");
let Json(mutation) = ob.flush().unwrap();
assert_eq!(mutation, Some(append!(_, json!("\n"))));
}
#[test]
fn test_deref_replace() {
let mut value = Box::new(String::from("Hello, World!"));
let mut ob = value.__observe();
assert_eq!(*ob, "Hello, World!");
****ob = String::from("42");
let Json(mutation) = ob.flush().unwrap();
assert_eq!(mutation, Some(replace!(_, json!("42"))));
}
#[test]
fn test_deref_assign() {
let mut value = Box::new(String::from("Hello, World!"));
let mut ob = value.__observe();
assert_eq!(*ob, "Hello, World!");
****ob = String::from("42");
let Json(mutation) = ob.flush().unwrap();
assert_eq!(mutation, Some(replace!(_, json!("42"))));
}
}