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 PartialEq
for InternedString
{
40 fn eq(&self, other
: &InternedString
) -> bool
{
41 ptr
::eq(self.as_str(), other
.as_str())
45 impl Eq
for InternedString {}
48 pub fn new(str: &str) -> InternedString
{
49 let mut cache
= STRING_CACHE
.lock().unwrap();
50 let s
= cache
.get(str).cloned().unwrap_or_else(|| {
51 let s
= leak(str.to_string());
56 InternedString { inner: s }
59 pub fn as_str(&self) -> &'
static str {
64 impl Deref
for InternedString
{
67 fn deref(&self) -> &'
static str {
72 impl AsRef
<str> for InternedString
{
73 fn as_ref(&self) -> &str {
78 impl AsRef
<OsStr
> for InternedString
{
79 fn as_ref(&self) -> &OsStr
{
80 self.as_str().as_ref()
84 impl AsRef
<Path
> for InternedString
{
85 fn as_ref(&self) -> &Path
{
86 self.as_str().as_ref()
90 impl Hash
for InternedString
{
91 // N.B., we can't implement this as `identity(self).hash(state)`,
92 // because we use this for on-disk fingerprints and so need
93 // stability across Cargo invocations.
94 fn hash
<H
: Hasher
>(&self, state
: &mut H
) {
95 self.as_str().hash(state
);
99 impl Borrow
<str> for InternedString
{
100 // If we implement Hash as `identity(self).hash(state)`,
101 // then this will need to be removed.
102 fn borrow(&self) -> &str {
107 impl fmt
::Debug
for InternedString
{
108 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
109 fmt
::Debug
::fmt(self.as_str(), f
)
113 impl fmt
::Display
for InternedString
{
114 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
115 fmt
::Display
::fmt(self.as_str(), f
)
119 impl Ord
for InternedString
{
120 fn cmp(&self, other
: &InternedString
) -> Ordering
{
121 self.as_str().cmp(other
.as_str())
125 impl PartialOrd
for InternedString
{
126 fn partial_cmp(&self, other
: &InternedString
) -> Option
<Ordering
> {
127 Some(self.cmp(other
))
131 impl Serialize
for InternedString
{
132 fn serialize
<S
>(&self, serializer
: S
) -> Result
<S
::Ok
, S
::Error
>
136 serializer
.serialize_str(self.inner
)
140 struct InternedStringVisitor
;
142 impl<'de
> serde
::Deserialize
<'de
> for InternedString
{
143 fn deserialize
<D
>(deserializer
: D
) -> Result
<Self, D
::Error
>
145 D
: serde
::Deserializer
<'de
>,
147 deserializer
.deserialize_str(InternedStringVisitor
)
151 impl<'de
> serde
::de
::Visitor
<'de
> for InternedStringVisitor
{
152 type Value
= InternedString
;
154 fn expecting(&self, formatter
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
155 formatter
.write_str("an String like thing")
158 fn visit_str
<E
>(self, v
: &str) -> Result
<Self::Value
, E
>
162 Ok(InternedString
::new(v
))