use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::Debug;
use std::ops::Deref;
use uuid::Uuid;
use weak_table::PtrWeakHashSet;
use weak_table::traits::WeakElement;
#[derive(Debug)]
pub struct Source<T>
where
T: Sized,
T: WeakElement,
<T as WeakElement>::Strong: Debug,
<T as WeakElement>::Strong: Deref,
{
senders: RefCell<PtrWeakHashSet<T>>,
}
impl<T> Source<T>
where
T: Sized,
T: WeakElement,
<T as WeakElement>::Strong: Debug,
<T as WeakElement>::Strong: Deref,
{
pub fn new() -> Source<T> {
Source {
senders: RefCell::new(PtrWeakHashSet::new()),
}
}
pub fn insert(&mut self, s: <T as WeakElement>::Strong) -> bool {
self.senders.borrow_mut().insert(s)
}
}
pub struct Target<T> {
senders: RefCell<HashMap<Uuid, T>>,
}
impl<T> Target<T>
where
T: Clone,
{
pub fn new() -> Target<T> {
Target {
senders: RefCell::new(HashMap::new()),
}
}
pub fn add(&mut self, id: Uuid, s: &T) {
let mut end_points = self.senders.borrow_mut();
end_points.entry(id).or_insert_with(|| s.clone());
}
pub fn look_up(&self, id: Uuid) -> Option<T> {
self.senders.borrow().get(&id).cloned()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::rc::{Rc, Weak};
#[test]
fn test_source() {
type Table = Source<Weak<str>>;
let mut map = Table::new();
let a = Rc::<str>::from("a");
assert!(!map.insert(Rc::clone(&a)));
let b = Rc::<str>::from("b");
assert!(!map.insert(Rc::clone(&b)));
assert!(map.insert(Rc::clone(&a)));
assert!(map.insert(Rc::clone(&b)));
drop(a);
assert!(map.insert(Rc::clone(&b)));
let c = Rc::<str>::from("c");
assert!(!map.insert(c));
}
#[test]
fn test_target() {
type Table = Target<u32>;
let mut map = Table::new();
let u = Uuid::new_v4();
assert_eq!(map.look_up(u), None);
map.add(u, &1);
map.add(u, &1);
let val = map.look_up(u);
assert_eq!(val, Some(1));
map.add(u, &2);
let u2 = Uuid::new_v4();
map.add(u2, &3);
let u3 = Uuid::new_v4();
map.add(u3, &1);
}
#[test]
fn test_source_with_target() {
type SourceTable = Source<Weak<u32>>;
type TargetTable = Target<Rc<u32>>;
let mut source_map = SourceTable::new();
let a = Rc::<u32>::from(1);
let id = Uuid::new_v4();
let already_sent = source_map.insert(Rc::clone(&a));
assert!(!already_sent);
let mut target_map = TargetTable::new();
target_map.add(id, &a);
let already_sent2 = source_map.insert(Rc::clone(&a));
assert!(already_sent2);
let val = target_map.look_up(id);
assert_eq!(val, Some(a.clone()));
}
}