wrc 0.2.0

A thread-safe weighted reference counting smart-pointer for Rust.
use std::sync::Mutex;
use std::ops::Deref;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use weight::Weight;

// The WRC `Inner` value uses `Mutex<usize>` to store the total weight value,
// meaning that mutations of the weight are thread-safe.
pub struct Inner<T: ?Sized> {
    weight: Mutex<usize>,
    data: T,
}

impl<T> Inner<T> {
    #[inline]
    pub fn new(data: T, starting_weight: usize) -> Inner<T> {
        Inner {
            weight: Mutex::new(starting_weight),
            data: data,
        }
    }

    #[inline]
    fn data(&self) -> &T {
        &self.data
    }
}

unsafe impl<T: ?Sized + Sync + Send> Send for Inner<T> {}
unsafe impl<T: ?Sized + Sync + Send> Sync for Inner<T> {}

impl<T: ?Sized> Weight for Inner<T> {
    fn add_weight(&self, weight: usize) -> Option<usize> {
        let mut existing_weight = self.weight.lock().expect("Unable to acquire WRC inner lock");
        let new_weight = existing_weight.checked_add(weight);
        match new_weight {
            Some(weight) => {
                *existing_weight = weight;
                Some(weight)
            }
            None => None,
        }
    }

    fn drop_weight(&self, weight: usize) -> Option<usize> {
        let mut existing_weight = self.weight.lock().expect("Unable to acquire WRC inner lock");
        let new_weight = existing_weight.checked_sub(weight);
        match new_weight {
            Some(weight) => {
                *existing_weight = weight;
                Some(weight)
            }
            None => None,
        }
    }

    fn get_weight(&self) -> usize {
        self.weight.lock().expect("Unable to acquire WRC inner lock").clone()
    }
}

impl<T> Deref for Inner<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        &self.data()
    }
}

impl<T> fmt::Display for Inner<T> where T: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.data(), f)
    }
}

impl<T> fmt::Debug for Inner<T> where T: fmt::Debug {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.data(), f)
    }
}

impl<T: ?Sized + PartialEq> PartialEq for Inner<T> {
    fn eq(&self, other: &Inner<T>) ->  bool {
        self.data == other.data
    }

    fn ne(&self, other: &Inner<T>) -> bool {
        self.data != other.data
    }
}

impl<T: PartialOrd> PartialOrd for Inner<T> {
    fn partial_cmp(&self, other: &Inner<T>) -> Option<Ordering> {
        self.data.partial_cmp(&other.data)
    }

    fn lt(&self, other: &Inner<T>) -> bool {
        self.data < other.data
    }

    fn le(&self, other: &Inner<T>) -> bool {
        self.data <= other.data
    }

    fn gt(&self, other: &Inner<T>) -> bool {
        self.data > other.data
    }

    fn ge(&self, other: &Inner<T>) -> bool {
        self.data >= other.data
    }
}

impl<T: Ord> Ord for Inner<T> {
    fn cmp(&self, other: &Inner<T>) -> Ordering {
        self.data.cmp(&other.data)
    }
}

impl<T: Eq> Eq for Inner<T> {}

impl<T: Hash> Hash for Inner<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.data.hash(state)
    }
}