1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

use crate::prelude::*;

#[derive(Debug, Default)]
pub struct Mutex<T>(parking_lot::Mutex<T>);

#[derive(Debug, Display)]
pub struct MutexGuard<'g, T>(parking_lot::MutexGuard<'g, T>)
where T: DebugIdentify;

impl<T> Mutex<T> where T: DebugIdentify {
  pub fn new(t: T) -> Self {
    Mutex(parking_lot::Mutex::new(t))
  }
  pub fn lock(&self) -> MutexGuard<T> {
    dbg!(dtype::<T>());
    let r = MutexGuard(self.0.lock());
    dbg!(dident(&*r));
    r
  }
}

impl<'g,T> Deref for MutexGuard<'g,T> where T: DebugIdentify {
  type Target = T;
  fn deref(&self) -> &T { &*self.0 }
}
impl<'g,T> DerefMut for MutexGuard<'g,T> where T: DebugIdentify {
  fn deref_mut(&mut self) -> &mut T { &mut *self.0 }
}

impl<'g,T> Drop for MutexGuard<'g,T> where T: DebugIdentify {
  fn drop(&mut self) {
    dbg!(dident(&**self));
  }
}

pub fn dtype<T: DebugIdentify>() -> impl Debug {
  DebugFormatter(T::debug_identify_type)
}
pub fn dident<'t, T: DebugIdentify>(t: &'t T) -> impl Debug + 't {
  DebugFormatter(move |f: &'_ mut fmt::Formatter<'_>| t.debug_identify(f))
}

pub struct DebugFormatter<C>(C);
impl<C> Debug for DebugFormatter<C>
where C: for<'f,'ff> Fn(&'f mut fmt::Formatter<'ff>) -> fmt::Result {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0(f) }
}

pub struct DebugDebugIdentify<'t,T>(&'t T) where T: DebugIdentify;
impl<T> Debug for DebugDebugIdentify<'_,T> where T: DebugIdentify {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    self.0.debug_identify(f)
  }
}

pub trait DebugIdentify {
  fn debug_identify_type(f: &mut fmt::Formatter) -> fmt::Result;
  fn debug_identify(&self, f: &mut fmt::Formatter) -> fmt::Result {
    Self::debug_identify_type(f)?;
    write!(f, "({:?})", self as *const _)?;
    Ok(())
  }
}

impl<T> DebugIdentify for Option<T> where T: DebugIdentify {
  #[throws(fmt::Error)]
  fn debug_identify_type(f: &mut fmt::Formatter) {
    write!(f, "Option<{:?}>", DebugFormatter(T::debug_identify_type))?;
  }

  #[throws(fmt::Error)]
  fn debug_identify(&self, f: &mut fmt::Formatter) {
    match self {
      None => write!(f, "None<{:?}>", DebugFormatter(T::debug_identify_type))?,
      Some(t) => t.debug_identify(f)?,
    }
  }
}

impl<T> DebugIdentify for VecDeque<T> where T: DebugIdentify {
  #[throws(fmt::Error)]
  fn debug_identify_type(f: &mut fmt::Formatter) {
    write!(f, "VecDeque<{:?}>", DebugFormatter(T::debug_identify_type))?;
  }
}

impl DebugIdentify for File{
  #[throws(fmt::Error)]
  fn debug_identify_type(f: &mut fmt::Formatter) {
    write!(f, "File")?;
  }

  #[throws(fmt::Error)]
  fn debug_identify(&self, f: &mut fmt::Formatter) {
    write!(f, "File({})", self.as_raw_fd())?;
  }
}