1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use std::{
cell::RefCell,
fmt::{self, Display},
hash::{BuildHasherDefault, Hash, Hasher},
ops::Deref,
rc::Rc,
};
#[derive(Clone, PartialOrd, Ord, Eq)]
pub struct IStr(Rc<str>);
impl Finalize for IStr {}
unsafe impl Trace for IStr {
unsafe_empty_trace!();
}
impl Deref for IStr {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl PartialEq for IStr {
fn eq(&self, other: &Self) -> bool {
Rc::ptr_eq(&self.0, &other.0)
}
}
impl PartialEq<str> for IStr {
fn eq(&self, other: &str) -> bool {
&self.0 as &str == other
}
}
impl Hash for IStr {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_usize(Rc::as_ptr(&self.0) as *const () as usize)
}
}
impl Drop for IStr {
fn drop(&mut self) {
if Rc::strong_count(&self.0) <= 2 {
let _result = STR_POOL.try_with(|pool| pool.borrow_mut().remove(&self.0));
}
}
}
impl fmt::Debug for IStr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", &self.0)
}
}
impl Display for IStr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
thread_local! {
static STR_POOL: RefCell<FxHashMap<Rc<str>, ()>> = RefCell::new(FxHashMap::with_capacity_and_hasher(200, BuildHasherDefault::default()));
}
impl From<&str> for IStr {
fn from(str: &str) -> Self {
IStr(STR_POOL.with(|pool| {
let mut pool = pool.borrow_mut();
if let Some((k, _)) = pool.get_key_value(str) {
k.clone()
} else {
let rc: Rc<str> = str.into();
pool.insert(rc.clone(), ());
rc
}
}))
}
}
impl From<String> for IStr {
fn from(str: String) -> Self {
(&str as &str).into()
}
}
impl Serialize for IStr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
(&self.0 as &str).serialize(serializer)
}
}
impl<'de> Deserialize<'de> for IStr {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = <&str>::deserialize(deserializer)?;
Ok(s.into())
}
}