Skip to content

Commit

Permalink
Avoid realloc in CString::new
Browse files Browse the repository at this point in the history
  • Loading branch information
sinkuu committed Oct 18, 2019
1 parent fa0f7d0 commit 23cb1d5
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 4 deletions.
4 changes: 1 addition & 3 deletions src/librustc_codegen_llvm/back/lto.rs
Expand Up @@ -53,9 +53,7 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,

let symbol_filter = &|&(ref name, level): &(String, SymbolExportLevel)| {
if level.is_below_threshold(export_threshold) {
let mut bytes = Vec::with_capacity(name.len() + 1);
bytes.extend(name.bytes());
Some(CString::new(bytes).unwrap())
Some(CString::new(name.as_str()).unwrap())
} else {
None
}
Expand Down
26 changes: 25 additions & 1 deletion src/libstd/ffi/c_str.rs
Expand Up @@ -327,7 +327,31 @@ impl CString {
/// [`NulError`]: struct.NulError.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
Self::_new(t.into())
trait SpecIntoVec {
fn into_vec(self) -> Vec<u8>;
}
impl<T: Into<Vec<u8>>> SpecIntoVec for T {
default fn into_vec(self) -> Vec<u8> {
self.into()
}
}
// Specialization for avoiding reallocation.
impl SpecIntoVec for &'_ [u8] {
fn into_vec(self) -> Vec<u8> {
let mut v = Vec::with_capacity(self.len() + 1);
v.extend(self);
v
}
}
impl SpecIntoVec for &'_ str {
fn into_vec(self) -> Vec<u8> {
let mut v = Vec::with_capacity(self.len() + 1);
v.extend(self.as_bytes());
v
}
}

Self::_new(SpecIntoVec::into_vec(t))
}

fn _new(bytes: Vec<u8>) -> Result<CString, NulError> {
Expand Down
1 change: 1 addition & 0 deletions src/libstd/lib.rs
Expand Up @@ -297,6 +297,7 @@
#![feature(slice_concat_ext)]
#![feature(slice_internals)]
#![feature(slice_patterns)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(stdsimd)]
Expand Down

0 comments on commit 23cb1d5

Please sign in to comment.