1# weak-table: weak hash maps and sets for Rust 2 3[![Build Status](https://travis-ci.org/tov/weak-table-rs.svg?branch=master)](https://travis-ci.org/tov/weak-table-rs) 4[![Crates.io](https://img.shields.io/crates/v/weak-table.svg?maxAge=2592000)](https://crates.io/crates/weak-table) 5[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT) 6 7This crate defines several kinds of weak hash maps and sets. See 8the [full API documentation](http://docs.rs/weak-table/) for details. 9 10This crate supports Rust version 1.32 and later. 11 12### Examples 13 14Here we create a weak hash map and demonstrate that it forgets mappings 15whose keys expire: 16 17```rust 18use weak_table::WeakKeyHashMap; 19use std::sync::{Arc, Weak}; 20 21let mut table = <WeakKeyHashMap<Weak<str>, u32>>::new(); 22let one = Arc::<str>::from("one"); 23let two = Arc::<str>::from("two"); 24 25table.insert(one.clone(), 1); 26 27assert_eq!( table.get("one"), Some(&1) ); 28assert_eq!( table.get("two"), None ); 29 30table.insert(two.clone(), 2); 31*table.get_mut(&one).unwrap() += 10; 32 33assert_eq!( table.get("one"), Some(&11) ); 34assert_eq!( table.get("two"), Some(&2) ); 35 36drop(one); 37 38assert_eq!( table.get("one"), None ); 39assert_eq!( table.get("two"), Some(&2) ); 40``` 41 42Here we use a weak hash set to implement a simple string interning facility: 43 44```rust 45use weak_table::WeakHashSet; 46use std::ops::Deref; 47use std::rc::{Rc, Weak}; 48 49#[derive(Clone, Debug)] 50pub struct Symbol(Rc<str>); 51 52impl PartialEq for Symbol { 53 fn eq(&self, other: &Symbol) -> bool { 54 Rc::ptr_eq(&self.0, &other.0) 55 } 56} 57 58impl Eq for Symbol {} 59 60impl Deref for Symbol { 61 type Target = str; 62 fn deref(&self) -> &str { 63 &self.0 64 } 65} 66 67#[derive(Debug, Default)] 68pub struct SymbolTable(WeakHashSet<Weak<str>>); 69 70impl SymbolTable { 71 pub fn new() -> Self { 72 Self::default() 73 } 74 75 pub fn intern(&mut self, name: &str) -> Symbol { 76 if let Some(rc) = self.0.get(name) { 77 Symbol(rc) 78 } else { 79 let rc = Rc::<str>::from(name); 80 self.0.insert(Rc::clone(&rc)); 81 Symbol(rc) 82 } 83 } 84} 85 86#[test] 87fn interning() { 88 let mut tab = SymbolTable::new(); 89 90 let a0 = tab.intern("a"); 91 let a1 = tab.intern("a"); 92 let b = tab.intern("b"); 93 94 assert_eq!(a0, a1); 95 assert_ne!(a0, b); 96} 97``` 98 99