use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, RwLock};
use by_address::ByAddress;
#[derive(Debug, Default)]
pub struct Ptr<T: ?Sized>(ByAddress<Arc<RwLock<T>>>);
impl<T> Ptr<T> {
pub fn new(i: T) -> Self {
Self(ByAddress(Arc::new(RwLock::new(i))))
}
}
impl<T> From<T> for Ptr<T> {
fn from(t: T) -> Self {
Self::new(t)
}
}
impl<T> Deref for Ptr<T> {
type Target = ByAddress<Arc<RwLock<T>>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for Ptr<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> Clone for Ptr<T> {
fn clone(&self) -> Self {
Self(ByAddress::clone(&self.0))
}
}
impl<T> PartialEq for Ptr<T> {
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
}
impl<T> Eq for Ptr<T> {}
impl<T> Hash for Ptr<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state)
}
}
#[derive(Debug, Clone)]
pub struct PtrList<T: ?Sized>(Vec<Ptr<T>>);
impl<T> PtrList<T> {
pub fn new() -> Self {
Self(Vec::new())
}
pub fn from_ptrs(ptrs: Vec<Ptr<T>>) -> Self {
Self(ptrs)
}
pub fn from_owned(vals: Vec<T>) -> Self {
let ptrs = vals.into_iter().map(|v| Ptr::new(v)).collect();
Self(ptrs)
}
pub fn add(&mut self, t: impl Into<T>) -> Ptr<T> {
let t = Ptr::new(t.into()); self.0.push(t.clone()); t }
pub fn insert(&mut self, t: impl Into<T>) -> Ptr<T> {
self.add(t)
}
}
impl<T> Default for PtrList<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Deref for PtrList<T> {
type Target = Vec<Ptr<T>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for PtrList<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> From<Vec<Ptr<T>>> for PtrList<T> {
fn from(v: Vec<Ptr<T>>) -> Self {
Self::from_ptrs(v)
}
}
impl<T> From<Vec<T>> for PtrList<T> {
fn from(v: Vec<T>) -> Self {
Self::from_owned(v)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ptr() {
let p1 = Ptr::new(43);
let p2 = Ptr::new(43);
assert_ne!(p1, p2);
let p3 = p1.clone();
assert_ne!(p3, p2);
assert_eq!(p3, p1);
}
#[test]
fn test_ptr_list() {
let mut list = PtrList::<bool>::new();
let p = list.add(true);
assert_eq!(list.len(), 1);
assert_eq!(*p.read().unwrap(), true);
let p = list.insert(false);
assert_eq!(list.len(), 2);
assert_eq!(*p.read().unwrap(), false);
list.push(Ptr::new(true));
assert_eq!(list.len(), 3);
assert_eq!(*list[2].read().unwrap(), true);
}
}