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
 99
100
101
102
103
104
105
use std::sync::{Arc, Mutex};
use std::hash::{Hash, Hasher};
use std::cmp::Ordering;
use std::ops::Deref;
use std::fmt;

#[cfg(feature = "compile")]
use serde::{Serialize, Deserialize};

use crate::{Value, TVal};

/// A reference to a `TVal`, locked via `Mutex`.
#[derive(Clone)]
#[cfg_attr(feature = "compile", derive(Serialize, Deserialize))]
pub struct RefTVal {
    val: Arc<Mutex<TVal>>,
}
impl RefTVal {
    /// Clones the `TVal` contained within this reference.
    ///
    /// # Panics
    /// Will panic if the `Mutex` is poisoned.
    #[must_use]
    pub fn clone_out(&self) -> TVal {
        (*self.val.lock().unwrap()).clone()
    }
    /// Clones this reference such that the clone no longer references the
    /// original.
    #[must_use]
    pub fn deep_clone(&self, attr: bool) -> RefTVal {
        let tv = self.clone_out();
        tv.deep_clone(attr).into()
    }
    /// Sets the interior value of the reference to the given value.
    ///
    /// # Panics
    /// Will panic if the `Mutex` is poisoned.
    pub fn set(&mut self, val: TVal) {
        *self.val.lock().unwrap() = val;
    }
}

impl PartialEq for RefTVal {
    fn eq(&self, other: &Self) -> bool {
        if Arc::as_ptr(&self.val) == Arc::as_ptr(&other.val) {
            return true;
        }
        *self.val.try_lock().unwrap() == *other.val.try_lock().unwrap()
    }
}
impl Eq for RefTVal {}

impl Hash for RefTVal {
    fn hash<H: Hasher>(&self, state: &mut H) {
        (*self.val.lock().unwrap()).hash(state);
    }
}

impl PartialOrd for RefTVal {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl Ord for RefTVal {
    fn cmp(&self, other: &Self) -> Ordering {
        (*self.val.try_lock().unwrap()).cmp(&*other.val.try_lock().unwrap())
    }
}

impl Deref for RefTVal {
    type Target = Mutex<TVal>;

    fn deref(&self) -> &Self::Target {
        &*self.val
    }
}

impl From<&str> for RefTVal {
    fn from(s: &str) -> Self {
        Value::String(s.into()).into()
    }
}
impl From<Value> for RefTVal {
    fn from(val: Value) -> Self {
        TVal::from(val).into()
    }
}
impl From<TVal> for RefTVal {
    fn from(tv: TVal) -> Self {
        RefTVal {
            val: Arc::new(Mutex::from(tv)),
        }
    }
}

impl fmt::Debug for RefTVal {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        <TVal as fmt::Debug>::fmt(&*self.val.lock().unwrap(), f)
    }
}
impl fmt::Display for RefTVal {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        <Self as fmt::Debug>::fmt(self, f)
    }
}