Here’s a polished README.md draft for your crate:
intern provides a thread-safe, memory-efficient interning system for Rust.
It allows you to deduplicate repeated values (like strings, symbols, or AST nodes) by storing them once and reusing references.
Interned values have pointer identity semantics: equality and hashing are based on the underlying Arc<T> pointer, not just the value.
- 🔒 Thread-safe — sharded lock-based design with low contention.
- ⚡ Fast lookups — O(1) average-case insertions using
FxHasher. - 🧹 Automatic cleanup — unused entries are dropped when no longer referenced.
- 📦 Flexible — works with
str,String,&'static str,Rc<str>,Arc<str>,Box<str>, andCow<str>. - 🛠️ Custom types — implement
Internableto intern your own types. - 🔄 Serde support (optional) — enable with
features = ["serde"].
use intern::Interned;
let a = Interned::from("hello");
let b = Interned::from("hello".to_string());
assert!(a.ptr_eq(&b)); // both point to the same Arc<str>use intern::{Internable, Interned, Interner};
#[derive(Eq, Hash, PartialEq)]
struct Symbol(&'static str);
impl Internable for Symbol {
fn interner() -> &'static Interner<Self> {
static INTERNER: Interner<Symbol> = Interner::new();
&INTERNER
}
}
let a = Symbol("hello").intern();
let b = Symbol("hello").intern();
assert!(a.ptr_eq(&b)); // pointer equality
assert_eq!(a, b); // value equality still worksA wrapper around Arc<T> with pointer identity semantics.
ptr_eq(&self, &Self) -> bool— fast pointer comparison.- Implements
Deref,Borrow,Eq,Hash,Clone,Serialize/Deserialize(withserde).
A trait for values that can be interned.
fn intern(self) -> Interned<Self>— interns the value.fn interner() -> &'static Interner<Self>— provides the global interner.
Thread-safe storage of interned values.
intern(value) -> Interned<T>— deduplicates or inserts a value.len() -> usize— number of distinct interned values.is_empty() -> bool.
- Sharded
HashMapreduces lock contention. - Intern/lookup: O(1) average-case.
- Uses
FxHasherfor speed (same asrustc). - Automatically removes unused values when their last reference is dropped.
Add to your Cargo.toml:
[dependencies]
intern = "0.1"Optional serde support:
[dependencies]
intern = { version = "0.1", features = ["serde"] }cargo testIncludes:
- ✅ Deduplication
- ✅ Equality & hashing
- ✅ Automatic cleanup
- ✅ Concurrency stress test
Interned values are stored in Arc<T>s.
When the last Interned<T> handle drops, the interner removes its entry, ensuring no leaks and safe reuse.
Licensed under either of:
- MIT License
- Apache License, Version 2.0
at your option.