Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slightly improve InternedString #5287

Merged
merged 1 commit into from
Apr 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 29 additions & 28 deletions src/cargo/core/interning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::collections::HashSet;
use std::slice;
use std::str;
use std::mem;
use std::ptr;
use std::cmp::Ordering;
use std::ops::Deref;
use std::hash::{Hash, Hasher};
Expand All @@ -24,65 +25,68 @@ lazy_static! {
RwLock::new(HashSet::new());
}

#[derive(Eq, PartialEq, Clone, Copy)]
#[derive(Clone, Copy)]
pub struct InternedString {
ptr: *const u8,
len: usize,
inner: &'static str,
}

impl PartialEq for InternedString {
fn eq(&self, other: &InternedString) -> bool {
ptr::eq(self.as_str(), other.as_str())
}
}

impl Eq for InternedString {}

impl InternedString {
pub fn new(str: &str) -> InternedString {
let mut cache = STRING_CACHE.write().unwrap();
if let Some(&s) = cache.get(str) {
return InternedString {
ptr: s.as_ptr(),
len: s.len(),
};
}
let s = leak(str.to_string());
cache.insert(s);
InternedString {
ptr: s.as_ptr(),
len: s.len(),
}
let s = cache.get(str).map(|&s| s).unwrap_or_else(|| {
let s = leak(str.to_string());
cache.insert(s);
s
});

InternedString { inner: s }
}
pub fn to_inner(&self) -> &'static str {
unsafe {
let slice = slice::from_raw_parts(self.ptr, self.len);
&str::from_utf8_unchecked(slice)
}

pub fn as_str(&self) -> &'static str {
self.inner
}
}

impl Deref for InternedString {
type Target = str;

fn deref(&self) -> &'static str {
self.to_inner()
self.as_str()
}
}

impl Hash for InternedString {
// NB: we can't implement this as `identity(self).hash(state)`,
// because we use this for on-disk fingerprints and so need
// stability across Cargo invocations.
fn hash<H: Hasher>(&self, state: &mut H) {
self.to_inner().hash(state);
self.as_str().hash(state);
}
}

impl fmt::Debug for InternedString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self.to_inner(), f)
fmt::Debug::fmt(self.as_str(), f)
}
}

impl fmt::Display for InternedString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self.to_inner(), f)
fmt::Display::fmt(self.as_str(), f)
}
}

impl Ord for InternedString {
fn cmp(&self, other: &InternedString) -> Ordering {
self.to_inner().cmp(&*other)
self.as_str().cmp(other.as_str())
}
}

Expand All @@ -91,6 +95,3 @@ impl PartialOrd for InternedString {
Some(self.cmp(other))
}
}

unsafe impl Send for InternedString {}
unsafe impl Sync for InternedString {}
2 changes: 1 addition & 1 deletion src/cargo/core/resolver/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ fn build_requirements<'a, 'b: 'a>(
reqs.require_feature(key)?;
}
for dep in s.dependencies().iter().filter(|d| d.is_optional()) {
reqs.require_dependency(dep.name().to_inner());
reqs.require_dependency(dep.name().as_str());
}
}
Method::Required {
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/cargo_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub fn doc(ws: &Workspace, options: &DocOptions) -> CargoResult<()> {
Please re-run this command with `-p <spec>` where `<spec>` \
is one of the following:\n {}",
pkgs.iter()
.map(|p| p.name().to_inner())
.map(|p| p.name().as_str())
.collect::<Vec<_>>()
.join("\n ")
);
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/cargo_generate_lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions) -> CargoResult<()>
resolve: &'a Resolve,
) -> Vec<(Vec<&'a PackageId>, Vec<&'a PackageId>)> {
fn key(dep: &PackageId) -> (&str, &SourceId) {
(dep.name().to_inner(), dep.source_id())
(dep.name().as_str(), dep.source_id())
}

// Removes all package ids in `b` from `a`. Note that this is somewhat
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/cargo_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ where
"multiple packages with {} found: {}",
kind,
pkgs.iter()
.map(|p| p.name().to_inner())
.map(|p| p.name().as_str())
.collect::<Vec<_>>()
.join(", ")
)
Expand Down