Skip to content

Instantly share code, notes, and snippets.

@clinuxrulz
Created August 12, 2021 12:05
Show Gist options
  • Save clinuxrulz/034c5a8f0564fccd1f62884a758e4df5 to your computer and use it in GitHub Desktop.
Save clinuxrulz/034c5a8f0564fccd1f62884a758e4df5 to your computer and use it in GitHub Desktop.
Recycling strings in Rust
use std::cell::RefCell;
use std::collections::HashSet;
use std::hash::{Hash, Hasher};
use std::rc::Rc;
thread_local! {
static STRING_FACTORY: RefCell<StringFactory> = RefCell::new(StringFactory::new());
}
struct MyRc<A>(Rc<A>);
impl<A:PartialEq> PartialEq for MyRc<A> {
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
}
impl<A:Eq> Eq for MyRc<A> {}
impl<A:Hash> Hash for MyRc<A> {
fn hash<H>(&self, state: &mut H) where H: Hasher {
self.0.hash(state);
}
}
impl std::borrow::Borrow<str> for MyRc<String> {
fn borrow(&self) -> &str {
&*self.0
}
}
pub struct StringFactory {
data: HashSet<MyRc<String>>,
}
impl StringFactory {
fn new() -> StringFactory {
StringFactory {
data: HashSet::new(),
}
}
pub fn collect() {
STRING_FACTORY.with(|self_| {
let mut self_ = self_.borrow_mut();
self_.data.retain(|x| Rc::strong_count(&x.0) > 1);
});
}
pub fn get_string(str: &str) -> Rc<String> {
STRING_FACTORY.with(|self_| {
let mut self_ = self_.borrow_mut();
if let Some(x) = self_.data.get(str) {
return Rc::clone(&x.0);
}
let r = Rc::new(str.into());
self_.data.insert(MyRc(Rc::clone(&r)));
r
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment