]> git.proxmox.com Git - cargo.git/blame - src/cargo/core/interning.rs
Add comment on relationship of RunCustomBuild and UnitFor::host.
[cargo.git] / src / cargo / core / interning.rs
CommitLineData
7b542268 1use serde::{Serialize, Serializer};
f4ef4163 2use std::borrow::Borrow;
827fdf84 3use std::cmp::Ordering;
f4ef4163 4use std::collections::HashSet;
593a02f2 5use std::ffi::OsStr;
f4ef4163 6use std::fmt;
8323081c 7use std::hash::{Hash, Hasher};
f4ef4163 8use std::ops::Deref;
593a02f2 9use std::path::Path;
f4ef4163
E
10use std::ptr;
11use std::str;
12use std::sync::Mutex;
26bfc7de 13
c036952f 14pub fn leak(s: String) -> &'static str {
19cb91fc 15 Box::leak(s.into_boxed_str())
26bfc7de 16}
1f764c55 17
9ed82b57 18lazy_static::lazy_static! {
f4ef4163 19 static ref STRING_CACHE: Mutex<HashSet<&'static str>> = Mutex::new(HashSet::new());
1f764c55
E
20}
21
d9880c3d 22#[derive(Clone, Copy)]
1f764c55 23pub struct InternedString {
d9880c3d 24 inner: &'static str,
1f764c55
E
25}
26
c14bb6e0
E
27impl<'a> From<&'a str> for InternedString {
28 fn from(item: &'a str) -> Self {
29 InternedString::new(item)
30 }
31}
32
33impl<'a> From<&'a String> for InternedString {
34 fn from(item: &'a String) -> Self {
35 InternedString::new(item)
36 }
37}
38
ef425b77
AC
39impl From<String> for InternedString {
40 fn from(item: String) -> Self {
41 InternedString::new(&item)
42 }
43}
44
d9880c3d
AK
45impl PartialEq for InternedString {
46 fn eq(&self, other: &InternedString) -> bool {
47 ptr::eq(self.as_str(), other.as_str())
48 }
49}
50
77ee608d
EH
51impl PartialEq<str> for InternedString {
52 fn eq(&self, other: &str) -> bool {
53 *self == other
54 }
55}
56
57impl<'a> PartialEq<&'a str> for InternedString {
58 fn eq(&self, other: &&str) -> bool {
59 **self == **other
60 }
61}
62
d9880c3d
AK
63impl Eq for InternedString {}
64
1f764c55
E
65impl InternedString {
66 pub fn new(str: &str) -> InternedString {
d6d57589 67 let mut cache = STRING_CACHE.lock().unwrap();
e5a11190 68 let s = cache.get(str).cloned().unwrap_or_else(|| {
d9880c3d
AK
69 let s = leak(str.to_string());
70 cache.insert(s);
71 s
72 });
73
74 InternedString { inner: s }
1f764c55 75 }
d9880c3d
AK
76
77 pub fn as_str(&self) -> &'static str {
78 self.inner
8323081c 79 }
98480e85
E
80}
81
82impl Deref for InternedString {
83 type Target = str;
84
85 fn deref(&self) -> &'static str {
d9880c3d 86 self.as_str()
8323081c
E
87 }
88}
89
c14bb6e0
E
90impl AsRef<str> for InternedString {
91 fn as_ref(&self) -> &str {
92 self.as_str()
93 }
94}
95
593a02f2
AC
96impl AsRef<OsStr> for InternedString {
97 fn as_ref(&self) -> &OsStr {
98 self.as_str().as_ref()
99 }
100}
101
102impl AsRef<Path> for InternedString {
103 fn as_ref(&self) -> &Path {
104 self.as_str().as_ref()
105 }
106}
107
8323081c 108impl Hash for InternedString {
f7c91ba6 109 // N.B., we can't implement this as `identity(self).hash(state)`,
d9880c3d
AK
110 // because we use this for on-disk fingerprints and so need
111 // stability across Cargo invocations.
8323081c 112 fn hash<H: Hasher>(&self, state: &mut H) {
d9880c3d 113 self.as_str().hash(state);
aa58d27a 114 }
1f764c55
E
115}
116
f4ef4163 117impl Borrow<str> for InternedString {
f7c91ba6 118 // If we implement Hash as `identity(self).hash(state)`,
b4cd6095 119 // then this will need to be removed.
f4ef4163
E
120 fn borrow(&self) -> &str {
121 self.as_str()
122 }
123}
124
9b731821 125impl fmt::Debug for InternedString {
b8b7faee 126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
d9880c3d 127 fmt::Debug::fmt(self.as_str(), f)
8323081c
E
128 }
129}
130
131impl fmt::Display for InternedString {
b8b7faee 132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
d9880c3d 133 fmt::Display::fmt(self.as_str(), f)
9b731821
E
134 }
135}
136
827fdf84
E
137impl Ord for InternedString {
138 fn cmp(&self, other: &InternedString) -> Ordering {
d9880c3d 139 self.as_str().cmp(other.as_str())
827fdf84
E
140 }
141}
142
143impl PartialOrd for InternedString {
144 fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
145 Some(self.cmp(other))
146 }
147}
7b542268
DO
148
149impl Serialize for InternedString {
150 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
151 where
152 S: Serializer,
153 {
154 serializer.serialize_str(self.inner)
155 }
156}
c14bb6e0
E
157
158struct InternedStringVisitor;
159
160impl<'de> serde::Deserialize<'de> for InternedString {
161 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
162 where
163 D: serde::Deserializer<'de>,
164 {
165 deserializer.deserialize_str(InternedStringVisitor)
166 }
167}
168
169impl<'de> serde::de::Visitor<'de> for InternedStringVisitor {
170 type Value = InternedString;
171
172 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
173 formatter.write_str("an String like thing")
174 }
175
176 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
177 where
178 E: serde::de::Error,
179 {
180 Ok(InternedString::new(v))
181 }
182}