1 use serde
::{Serialize, Serializer}
;
2 use std
::borrow
::Borrow
;
3 use std
::cmp
::Ordering
;
4 use std
::collections
::HashSet
;
7 use std
::hash
::{Hash, Hasher}
;
14 pub fn leak(s
: String
) -> &'
static str {
15 Box
::leak(s
.into_boxed_str())
18 lazy_static
::lazy_static
! {
19 static ref STRING_CACHE
: Mutex
<HashSet
<&'
static str>> = Mutex
::new(HashSet
::new());
22 #[derive(Clone, Copy)]
23 pub struct InternedString
{
27 impl<'a
> From
<&'a
str> for InternedString
{
28 fn from(item
: &'a
str) -> Self {
29 InternedString
::new(item
)
33 impl<'a
> From
<&'a String
> for InternedString
{
34 fn from(item
: &'a String
) -> Self {
35 InternedString
::new(item
)
39 impl From
<String
> for InternedString
{
40 fn from(item
: String
) -> Self {
41 InternedString
::new(&item
)
45 impl PartialEq
for InternedString
{
46 fn eq(&self, other
: &InternedString
) -> bool
{
47 ptr
::eq(self.as_str(), other
.as_str())
51 impl PartialEq
<str> for InternedString
{
52 fn eq(&self, other
: &str) -> bool
{
57 impl<'a
> PartialEq
<&'a
str> for InternedString
{
58 fn eq(&self, other
: &&str) -> bool
{
63 impl Eq
for InternedString {}
66 pub fn new(str: &str) -> InternedString
{
67 let mut cache
= STRING_CACHE
.lock().unwrap();
68 let s
= cache
.get(str).cloned().unwrap_or_else(|| {
69 let s
= leak(str.to_string());
74 InternedString { inner: s }
77 pub fn as_str(&self) -> &'
static str {
82 impl Deref
for InternedString
{
85 fn deref(&self) -> &'
static str {
90 impl AsRef
<str> for InternedString
{
91 fn as_ref(&self) -> &str {
96 impl AsRef
<OsStr
> for InternedString
{
97 fn as_ref(&self) -> &OsStr
{
98 self.as_str().as_ref()
102 impl AsRef
<Path
> for InternedString
{
103 fn as_ref(&self) -> &Path
{
104 self.as_str().as_ref()
108 impl Hash
for InternedString
{
109 // N.B., we can't implement this as `identity(self).hash(state)`,
110 // because we use this for on-disk fingerprints and so need
111 // stability across Cargo invocations.
112 fn hash
<H
: Hasher
>(&self, state
: &mut H
) {
113 self.as_str().hash(state
);
117 impl Borrow
<str> for InternedString
{
118 // If we implement Hash as `identity(self).hash(state)`,
119 // then this will need to be removed.
120 fn borrow(&self) -> &str {
125 impl fmt
::Debug
for InternedString
{
126 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
127 fmt
::Debug
::fmt(self.as_str(), f
)
131 impl fmt
::Display
for InternedString
{
132 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
133 fmt
::Display
::fmt(self.as_str(), f
)
137 impl Ord
for InternedString
{
138 fn cmp(&self, other
: &InternedString
) -> Ordering
{
139 self.as_str().cmp(other
.as_str())
143 impl PartialOrd
for InternedString
{
144 fn partial_cmp(&self, other
: &InternedString
) -> Option
<Ordering
> {
145 Some(self.cmp(other
))
149 impl Serialize
for InternedString
{
150 fn serialize
<S
>(&self, serializer
: S
) -> Result
<S
::Ok
, S
::Error
>
154 serializer
.serialize_str(self.inner
)
158 struct InternedStringVisitor
;
160 impl<'de
> serde
::Deserialize
<'de
> for InternedString
{
161 fn deserialize
<D
>(deserializer
: D
) -> Result
<Self, D
::Error
>
163 D
: serde
::Deserializer
<'de
>,
165 deserializer
.deserialize_str(InternedStringVisitor
)
169 impl<'de
> serde
::de
::Visitor
<'de
> for InternedStringVisitor
{
170 type Value
= InternedString
;
172 fn expecting(&self, formatter
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
173 formatter
.write_str("an String like thing")
176 fn visit_str
<E
>(self, v
: &str) -> Result
<Self::Value
, E
>
180 Ok(InternedString
::new(v
))