]> git.lizzy.rs Git - rust.git/commitdiff
std: Redesign c_str and c_vec
authorAlex Crichton <alex@alexcrichton.com>
Tue, 25 Nov 2014 21:28:35 +0000 (13:28 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 5 Jan 2015 16:00:13 +0000 (08:00 -0800)
This commit is an implementation of [RFC 494][rfc] which removes the entire
`std::c_vec` module and redesigns the `std::c_str` module as `std::ffi`.

[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0494-c_str-and-c_vec-stability.md

The interface of the new `CString` is outlined in the linked RFC, the primary
changes being:

* The `ToCStr` trait is gone, meaning the `with_c_str` and `to_c_str` methods
  are now gone. These two methods are replaced with a `CString::from_slice`
  method.
* The `CString` type is now just a wrapper around `Vec<u8>` with a static
  guarantee that there is a trailing nul byte with no internal nul bytes. This
  means that `CString` now implements `Deref<Target = [c_char]>`, which is where
  it gains most of its methods from. A few helper methods are added to acquire a
  slice of `u8` instead of `c_char`, as well as including a slice with the
  trailing nul byte if necessary.
* All usage of non-owned `CString` values is now done via two functions inside
  of `std::ffi`, called `c_str_to_bytes` and `c_str_to_bytes_with_nul`. These
  functions are now the one method used to convert a `*const c_char` to a Rust
  slice of `u8`.

Many more details, including newly deprecated methods, can be found linked in
the RFC. This is a:

[breaking-change]
Closes #20444

59 files changed:
src/doc/guide-ffi.md
src/libcollections/string.rs
src/libcore/str/mod.rs
src/libflate/lib.rs
src/librustc/metadata/cstore.rs
src/librustc/metadata/loader.rs
src/librustc_llvm/archive_ro.rs
src/librustc_llvm/lib.rs
src/librustc_trans/back/lto.rs
src/librustc_trans/back/write.rs
src/librustc_trans/trans/asm.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/builder.rs
src/librustc_trans/trans/common.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/context.rs
src/librustc_trans/trans/debuginfo.rs
src/librustc_trans/trans/foreign.rs
src/librustc_trans/trans/glue.rs
src/librustc_trans/trans/meth.rs
src/librustc_trans/trans/type_.rs
src/librustdoc/flock.rs
src/librustdoc/html/markdown.rs
src/libstd/c_str.rs [deleted file]
src/libstd/c_vec.rs [deleted file]
src/libstd/dynamic_lib.rs
src/libstd/ffi/c_str.rs [new file with mode: 0644]
src/libstd/ffi/mod.rs [new file with mode: 0644]
src/libstd/io/net/pipe.rs
src/libstd/io/process.rs
src/libstd/lib.rs
src/libstd/os.rs
src/libstd/path/mod.rs
src/libstd/path/posix.rs
src/libstd/path/windows.rs
src/libstd/rt/args.rs
src/libstd/rt/backtrace.rs
src/libstd/rt/unwind.rs
src/libstd/rt/util.rs
src/libstd/sys/common/mod.rs
src/libstd/sys/common/net.rs
src/libstd/sys/unix/backtrace.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/pipe.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/timer.rs
src/libstd/sys/windows/backtrace.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/pipe.rs
src/libstd/sys/windows/process.rs
src/test/auxiliary/linkage-visibility.rs
src/test/run-pass/c-stack-returning-int64.rs
src/test/run-pass/const-str-ptr.rs
src/test/run-pass/foreign-fn-linkname.rs
src/test/run-pass/rename-directory.rs
src/test/run-pass/variadic-ffi.rs

index b8808eaf57d93e076b5b90829ecd0d45b5317202..7ee1c1a7032a5c4fce6975e1c9d0e0201fe4dbe7 100644 (file)
@@ -451,7 +451,7 @@ them.
 ~~~no_run
 extern crate libc;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::ptr;
 
 #[link(name = "readline")]
@@ -460,11 +460,10 @@ extern {
 }
 
 fn main() {
-    "[my-awesome-shell] $".with_c_str(|buf| {
-        unsafe { rl_prompt = buf; }
-        // get a line, process it
-        unsafe { rl_prompt = ptr::null(); }
-    });
+    let prompt = CString::from_slice(b"[my-awesome-shell] $");
+    unsafe { rl_prompt = prompt.as_ptr(); }
+    // get a line, process it
+    unsafe { rl_prompt = ptr::null(); }
 }
 ~~~
 
@@ -509,23 +508,28 @@ to define a block for all windows systems, not just x86 ones.
 
 # Interoperability with foreign code
 
-Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C
-only if the `#[repr(C)]` attribute is applied to it.  `#[repr(C, packed)]` can be used to lay out
-struct members without padding.  `#[repr(C)]` can also be applied to an enum.
-
-Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point to the contained
-object. However, they should not be manually created because they are managed by internal
-allocators. References can safely be assumed to be non-nullable pointers directly to the type.
-However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so prefer
-using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions about
-them.
-
-Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and
-`str` modules for working with C APIs. However, strings are not terminated with `\0`. If you need a
-NUL-terminated string for interoperability with C, you should use the `c_str::to_c_str` function.
-
-The standard library includes type aliases and function definitions for the C standard library in
-the `libc` module, and Rust links against `libc` and `libm` by default.
+Rust guarantees that the layout of a `struct` is compatible with the platform's
+representation in C only if the `#[repr(C)]` attribute is applied to it.
+`#[repr(C, packed)]` can be used to lay out struct members without padding.
+`#[repr(C)]` can also be applied to an enum.
+
+Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point
+to the contained object. However, they should not be manually created because
+they are managed by internal allocators. References can safely be assumed to be
+non-nullable pointers directly to the type.  However, breaking the borrow
+checking or mutability rules is not guaranteed to be safe, so prefer using raw
+pointers (`*`) if that's needed because the compiler can't make as many
+assumptions about them.
+
+Vectors and strings share the same basic memory layout, and utilities are
+available in the `vec` and `str` modules for working with C APIs. However,
+strings are not terminated with `\0`. If you need a NUL-terminated string for
+interoperability with C, you should use the `CString` type in the `std::ffi`
+module.
+
+The standard library includes type aliases and function definitions for the C
+standard library in the `libc` module, and Rust links against `libc` and `libm`
+by default.
 
 # The "nullable pointer optimization"
 
index e7451331908aed9e8fdf2fefb3ed60790b63e9dc..11e6c48cfdbad52209f5eaefbe1c34f22183baa3 100644 (file)
@@ -320,30 +320,6 @@ pub unsafe fn from_raw_parts(buf: *mut u8, length: uint, capacity: uint) -> Stri
         }
     }
 
-    /// Creates a `String` from a null-terminated `*const u8` buffer.
-    ///
-    /// This function is unsafe because we dereference memory until we find the
-    /// NUL character, which is not guaranteed to be present. Additionally, the
-    /// slice is not checked to see whether it contains valid UTF-8
-    #[unstable = "just renamed from `mod raw`"]
-    pub unsafe fn from_raw_buf(buf: *const u8) -> String {
-        String::from_str(str::from_c_str(buf as *const i8))
-    }
-
-    /// Creates a `String` from a `*const u8` buffer of the given length.
-    ///
-    /// This function is unsafe because it blindly assumes the validity of the
-    /// pointer `buf` for `len` bytes of memory. This function will copy the
-    /// memory from `buf` into a new allocation (owned by the returned
-    /// `String`).
-    ///
-    /// This function is also unsafe because it does not validate that the
-    /// buffer is valid UTF-8 encoded data.
-    #[unstable = "just renamed from `mod raw`"]
-    pub unsafe fn from_raw_buf_len(buf: *const u8, len: uint) -> String {
-        String::from_utf8_unchecked(Vec::from_raw_buf(buf, len))
-    }
-
     /// Converts a vector of bytes to a new `String` without checking if
     /// it contains valid UTF-8. This is unsafe because it assumes that
     /// the UTF-8-ness of the vector has already been validated.
@@ -1126,24 +1102,6 @@ fn test_from_utf16_lossy() {
                    String::from_str("\u{FFFD}𐒋\u{FFFD}"));
     }
 
-    #[test]
-    fn test_from_buf_len() {
-        unsafe {
-            let a = vec![65u8, 65, 65, 65, 65, 65, 65, 0];
-            assert_eq!(String::from_raw_buf_len(a.as_ptr(), 3), String::from_str("AAA"));
-        }
-    }
-
-    #[test]
-    fn test_from_buf() {
-        unsafe {
-            let a = vec![65, 65, 65, 65, 65, 65, 65, 0];
-            let b = a.as_ptr();
-            let c = String::from_raw_buf(b);
-            assert_eq!(c, String::from_str("AAAAAAA"));
-        }
-    }
-
     #[test]
     fn test_push_bytes() {
         let mut s = String::from_str("ABC");
index d069744f8da54f109bba4c957240999bbbfa8258..8fdd66f83cee4c205d52827a970f6720222a5aca 100644 (file)
@@ -190,7 +190,7 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str {
 /// # Panics
 ///
 /// This function will panic if the string pointed to by `s` is not valid UTF-8.
-#[unstable = "may change location based on the outcome of the c_str module"]
+#[deprecated = "use std::ffi::c_str_to_bytes + str::from_utf8"]
 pub unsafe fn from_c_str(s: *const i8) -> &'static str {
     let s = s as *const u8;
     let mut len = 0u;
index aa1550ae5b874cfbfd5d08dfcfb82e4af1d4ccf9..a0c9da3ae6d497a3ddeb818a189c0b2a597f956c 100644 (file)
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/")]
-#![feature(phase, unboxed_closures)]
+#![feature(phase, unboxed_closures, associated_types)]
 
 #[cfg(test)] #[phase(plugin, link)] extern crate log;
 
 extern crate libc;
 
 use libc::{c_void, size_t, c_int};
-use std::c_vec::CVec;
+use std::ops::Deref;
 use std::ptr::Unique;
+use std::slice;
+
+pub struct Bytes {
+    ptr: Unique<u8>,
+    len: uint,
+}
+
+impl Deref for Bytes {
+    type Target = [u8];
+    fn deref(&self) -> &[u8] {
+        unsafe { slice::from_raw_mut_buf(&self.ptr.0, self.len) }
+    }
+}
+
+impl Drop for Bytes {
+    fn drop(&mut self) {
+        unsafe { libc::free(self.ptr.0 as *mut _); }
+    }
+}
 
 #[link(name = "miniz", kind = "static")]
 extern {
@@ -52,7 +71,7 @@ fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void,
 static TINFL_FLAG_PARSE_ZLIB_HEADER : c_int = 0x1; // parse zlib header and adler32 checksum
 static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler32 checksum
 
-fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
+fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
     unsafe {
         let mut outsz : size_t = 0;
         let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _,
@@ -60,8 +79,8 @@ fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
                                              &mut outsz,
                                              flags);
         if !res.is_null() {
-            let res = Unique(res);
-            Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0)))
+            let res = Unique(res as *mut u8);
+            Some(Bytes { ptr: res, len: outsz as uint })
         } else {
             None
         }
@@ -69,16 +88,16 @@ fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
 }
 
 /// Compress a buffer, without writing any sort of header on the output.
-pub fn deflate_bytes(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn deflate_bytes(bytes: &[u8]) -> Option<Bytes> {
     deflate_bytes_internal(bytes, LZ_NORM)
 }
 
 /// Compress a buffer, using a header that zlib can understand.
-pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
     deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
 }
 
-fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
+fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
     unsafe {
         let mut outsz : size_t = 0;
         let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
@@ -86,8 +105,8 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
                                                &mut outsz,
                                                flags);
         if !res.is_null() {
-            let res = Unique(res);
-            Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0)))
+            let res = Unique(res as *mut u8);
+            Some(Bytes { ptr: res, len: outsz as uint })
         } else {
             None
         }
@@ -95,12 +114,12 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
 }
 
 /// Decompress a buffer, without parsing any sort of header on the input.
-pub fn inflate_bytes(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn inflate_bytes(bytes: &[u8]) -> Option<Bytes> {
     inflate_bytes_internal(bytes, 0)
 }
 
 /// Decompress a buffer that starts with a zlib header.
-pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
     inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
 }
 
index 2f4acaca4de4d3eda8f5f1223da3182d9bd89f15..ec0b80c3a5342f26b6af6563ab6a628b0f2810b1 100644 (file)
@@ -23,8 +23,8 @@
 use util::nodemap::{FnvHashMap, NodeMap};
 
 use std::cell::RefCell;
-use std::c_vec::CVec;
 use std::rc::Rc;
+use flate::Bytes;
 use syntax::ast;
 use syntax::codemap::Span;
 use syntax::parse::token::IdentInterner;
@@ -36,7 +36,7 @@
 pub type cnum_map = FnvHashMap<ast::CrateNum, ast::CrateNum>;
 
 pub enum MetadataBlob {
-    MetadataVec(CVec<u8>),
+    MetadataVec(Bytes),
     MetadataArchive(loader::ArchiveMetadata),
 }
 
index c18bd421b3b077b61946b57b615bbefd756c892d..7c0645b4ca204037c451ef1c62f6232a7c547360 100644 (file)
 use syntax::diagnostic::SpanHandler;
 use util::fs;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::cmp;
 use std::collections::{HashMap, HashSet};
 use std::io::fs::PathExtensions;
@@ -720,9 +720,8 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
         }
     }
     unsafe {
-        let mb = filename.with_c_str(|buf| {
-            llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
-        });
+        let buf = CString::from_slice(filename.as_vec());
+        let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
         if mb as int == 0 {
             return Err(format!("error reading library: '{}'",
                                filename.display()))
@@ -738,8 +737,9 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
         while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
             let mut name_buf = ptr::null();
             let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
-            let name = String::from_raw_buf_len(name_buf as *const u8,
-                                                name_len as uint);
+            let name = slice::from_raw_buf(&(name_buf as *const u8),
+                                           name_len as uint).to_vec();
+            let name = String::from_utf8(name).unwrap();
             debug!("get_metadata_section: name {}", name);
             if read_meta_section_name(is_osx) == name {
                 let cbuf = llvm::LLVMGetSectionContents(si.llsi);
index 53992d4567a34915148e2c9e87957e05cbc81517..d3555e4c0436354055399d04ab1cbb2f58995c97 100644 (file)
@@ -13,7 +13,7 @@
 use libc;
 use ArchiveRef;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::mem;
 use std::raw;
 
@@ -30,9 +30,8 @@ impl ArchiveRO {
     /// raised.
     pub fn open(dst: &Path) -> Option<ArchiveRO> {
         unsafe {
-            let ar = dst.with_c_str(|dst| {
-                ::LLVMRustOpenArchive(dst)
-            });
+            let s = CString::from_slice(dst.as_vec());
+            let ar = ::LLVMRustOpenArchive(s.as_ptr());
             if ar.is_null() {
                 None
             } else {
@@ -45,9 +44,9 @@ pub fn open(dst: &Path) -> Option<ArchiveRO> {
     pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> {
         unsafe {
             let mut size = 0 as libc::size_t;
-            let ptr = file.with_c_str(|file| {
-                ::LLVMRustArchiveReadSection(self.ptr, file, &mut size)
-            });
+            let file = CString::from_slice(file.as_bytes());
+            let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(),
+                                                   &mut size);
             if ptr.is_null() {
                 None
             } else {
index 2ec5f37634afb35474c708bae64d1e8e9538d023..854ac5ff5c01cafedf48cc71c1cb8ad6f35d996e 100644 (file)
@@ -47,7 +47,7 @@
 pub use self::DiagnosticSeverity::*;
 pub use self::Linkage::*;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::cell::RefCell;
 use std::{raw, mem};
 use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
@@ -2114,10 +2114,9 @@ fn drop(&mut self) {
 }
 
 pub fn mk_target_data(string_rep: &str) -> TargetData {
+    let string_rep = CString::from_slice(string_rep.as_bytes());
     TargetData {
-        lltd: string_rep.with_c_str(|buf| {
-            unsafe { LLVMCreateTargetData(buf) }
-        })
+        lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) }
     }
 }
 
index c6488ec6638a3efe83d1a199c0d87277c592d5c0..f3e90c43a8414961bcdb979fb15f9dbada402d85 100644 (file)
@@ -20,7 +20,7 @@
 use libc;
 use flate;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::iter;
 use std::mem;
 use std::num::Int;
@@ -139,9 +139,10 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
     }
 
     // Internalize everything but the reachable symbols of the current module
-    let cstrs: Vec<::std::c_str::CString> =
-        reachable.iter().map(|s| s.to_c_str()).collect();
-    let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect();
+    let cstrs: Vec<CString> = reachable.iter().map(|s| {
+        CString::from_slice(s.as_bytes())
+    }).collect();
+    let arr: Vec<*const i8> = cstrs.iter().map(|c| c.as_ptr()).collect();
     let ptr = arr.as_ptr();
     unsafe {
         llvm::LLVMRustRunRestrictionPass(llmod,
@@ -164,7 +165,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
     unsafe {
         let pm = llvm::LLVMCreatePassManager();
         llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
-        "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));
+        llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
 
         let builder = llvm::LLVMPassManagerBuilderCreate();
         llvm::LLVMPassManagerBuilderPopulateLTOPassManager(builder, pm,
@@ -172,7 +173,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
             /* RunInliner = */ True);
         llvm::LLVMPassManagerBuilderDispose(builder);
 
-        "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));
+        llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
 
         time(sess.time_passes(), "LTO passes", (), |()|
              llvm::LLVMRunPassManager(pm, llmod));
index 33011d9e35c106b959033561f4c63b88e7fed919..089d7f737d3cf4703376bc9c4901c4d322fe38ea 100644 (file)
@@ -22,7 +22,7 @@
 use syntax::diagnostic;
 use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
 
-use std::c_str::{ToCStr, CString};
+use std::ffi::{mod, CString};
 use std::io::Command;
 use std::io::fs;
 use std::iter::Unfold;
@@ -32,7 +32,7 @@
 use std::sync::{Arc, Mutex};
 use std::sync::mpsc::channel;
 use std::thread;
-use libc::{c_uint, c_int, c_void};
+use libc::{mod, c_uint, c_int, c_void};
 
 #[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
 pub enum OutputType {
@@ -49,8 +49,9 @@ pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! {
         if cstr == ptr::null() {
             handler.fatal(msg[]);
         } else {
-            let err = CString::new(cstr, true);
-            let err = String::from_utf8_lossy(err.as_bytes());
+            let err = ffi::c_str_to_bytes(&cstr);
+            let err = String::from_utf8_lossy(err.as_slice()).to_string();
+            libc::free(cstr as *mut _);
             handler.fatal(format!("{}: {}",
                                   msg[],
                                   err[])[]);
@@ -66,13 +67,12 @@ pub fn write_output_file(
         output: &Path,
         file_type: llvm::FileType) {
     unsafe {
-        output.with_c_str(|output| {
-            let result = llvm::LLVMRustWriteOutputFile(
-                    target, pm, m, output, file_type);
-            if !result {
-                llvm_err(handler, "could not write output".to_string());
-            }
-        })
+        let output = CString::from_slice(output.as_vec());
+        let result = llvm::LLVMRustWriteOutputFile(
+                target, pm, m, output.as_ptr(), file_type);
+        if !result {
+            llvm_err(handler, "could not write output".to_string());
+        }
     }
 }
 
@@ -221,28 +221,25 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
     let triple = sess.target.target.llvm_target[];
 
     let tm = unsafe {
-        triple.with_c_str(|t| {
-            let cpu = match sess.opts.cg.target_cpu {
-                Some(ref s) => s[],
-                None => sess.target.target.options.cpu[]
-            };
-            cpu.with_c_str(|cpu| {
-                target_feature(sess).with_c_str(|features| {
-                    llvm::LLVMRustCreateTargetMachine(
-                        t, cpu, features,
-                        code_model,
-                        reloc_model,
-                        opt_level,
-                        true /* EnableSegstk */,
-                        use_softfp,
-                        no_fp_elim,
-                        !any_library && reloc_model == llvm::RelocPIC,
-                        ffunction_sections,
-                        fdata_sections,
-                    )
-                })
-            })
-        })
+        let triple = CString::from_slice(triple.as_bytes());
+        let cpu = match sess.opts.cg.target_cpu {
+            Some(ref s) => s.as_slice(),
+            None => sess.target.target.options.cpu.as_slice()
+        };
+        let cpu = CString::from_slice(cpu.as_bytes());
+        let features = CString::from_slice(target_feature(sess).as_bytes());
+        llvm::LLVMRustCreateTargetMachine(
+            triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
+            code_model,
+            reloc_model,
+            opt_level,
+            true /* EnableSegstk */,
+            use_softfp,
+            no_fp_elim,
+            !any_library && reloc_model == llvm::RelocPIC,
+            ffunction_sections,
+            fdata_sections,
+        )
     };
 
     if tm.is_null() {
@@ -371,8 +368,9 @@ struct HandlerFreeVars<'a> {
 
     match llvm::diagnostic::Diagnostic::unpack(info) {
         llvm::diagnostic::Optimization(opt) => {
-            let pass_name = CString::new(opt.pass_name, false);
-            let pass_name = pass_name.as_str().expect("got a non-UTF8 pass name from LLVM");
+            let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name))
+                                .ok()
+                                .expect("got a non-UTF8 pass name from LLVM");
             let enabled = match cgcx.remark {
                 AllPasses => true,
                 SomePasses(ref v) => v.iter().any(|s| *s == pass_name),
@@ -416,9 +414,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
 
     if config.emit_no_opt_bc {
         let ext = format!("{}.no-opt.bc", name_extra);
-        output_names.with_extension(ext[]).with_c_str(|buf| {
-            llvm::LLVMWriteBitcodeToFile(llmod, buf);
-        })
+        let out = output_names.with_extension(ext.as_slice());
+        let out = CString::from_slice(out.as_vec());
+        llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
     }
 
     match config.opt_level {
@@ -433,7 +431,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
             // If we're verifying or linting, add them to the function pass
             // manager.
             let addpass = |&: pass: &str| {
-                pass.with_c_str(|s| llvm::LLVMRustAddPass(fpm, s))
+                let pass = CString::from_slice(pass.as_bytes());
+                llvm::LLVMRustAddPass(fpm, pass.as_ptr())
             };
             if !config.no_verify { assert!(addpass("verify")); }
 
@@ -445,12 +444,11 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
             }
 
             for pass in config.passes.iter() {
-                pass.with_c_str(|s| {
-                    if !llvm::LLVMRustAddPass(mpm, s) {
-                        cgcx.handler.warn(format!("unknown pass {}, ignoring",
-                                                  *pass)[]);
-                    }
-                })
+                let pass = CString::from_slice(pass.as_bytes());
+                if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
+                    cgcx.handler.warn(format!("unknown pass {}, ignoring",
+                                              pass).as_slice());
+                }
             }
 
             // Finally, run the actual optimization passes
@@ -470,9 +468,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
 
                     if config.emit_lto_bc {
                         let name = format!("{}.lto.bc", name_extra);
-                        output_names.with_extension(name[]).with_c_str(|buf| {
-                            llvm::LLVMWriteBitcodeToFile(llmod, buf);
-                        })
+                        let out = output_names.with_extension(name.as_slice());
+                        let out = CString::from_slice(out.as_vec());
+                        llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
                     }
                 },
                 _ => {},
@@ -504,18 +502,18 @@ unsafe fn with_codegen<F>(tm: TargetMachineRef,
 
     if config.emit_bc {
         let ext = format!("{}.bc", name_extra);
-        output_names.with_extension(ext[]).with_c_str(|buf| {
-            llvm::LLVMWriteBitcodeToFile(llmod, buf);
-        })
+        let out = output_names.with_extension(ext.as_slice());
+        let out = CString::from_slice(out.as_vec());
+        llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
     }
 
     time(config.time_passes, "codegen passes", (), |()| {
         if config.emit_ir {
             let ext = format!("{}.ll", name_extra);
-            output_names.with_extension(ext[]).with_c_str(|output| {
-                with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                    llvm::LLVMRustPrintModule(cpm, llmod, output);
-                })
+            let out = output_names.with_extension(ext.as_slice());
+            let out = CString::from_slice(out.as_vec());
+            with_codegen(tm, llmod, config.no_builtins, |cpm| {
+                llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
             })
         }
 
@@ -995,7 +993,7 @@ unsafe fn configure_llvm(sess: &Session) {
     let mut llvm_args = Vec::new();
     {
         let mut add = |&mut : arg: &str| {
-            let s = arg.to_c_str();
+            let s = CString::from_slice(arg.as_bytes());
             llvm_args.push(s.as_ptr());
             llvm_c_strs.push(s);
         };
@@ -1083,7 +1081,7 @@ unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
 
     match opt {
         llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
-            "mergefunc".with_c_str(|s| llvm::LLVMRustAddPass(mpm, s));
+            llvm::LLVMRustAddPass(mpm, "mergefunc\0".as_ptr() as *const _);
         }
         _ => {}
     };
index 5597e112f76d1727f05d08a1febd1a599d1bb023..f18d483f70328bd3389cdc527f445b729c6247ff 100644 (file)
@@ -20,9 +20,8 @@
 use trans::type_of;
 use trans::type_::Type;
 
-use std::c_str::ToCStr;
-use std::string::String;
 use syntax::ast;
+use std::ffi::CString;
 use libc::{c_uint, c_char};
 
 // Take an inline assembly expression and splat it out via LLVM
@@ -121,18 +120,16 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
         ast::AsmIntel => llvm::AD_Intel
     };
 
-    let r = ia.asm.get().with_c_str(|a| {
-        constraints.with_c_str(|c| {
-            InlineAsmCall(bcx,
-                          a,
-                          c,
-                          inputs[],
+    let asm = CString::from_slice(ia.asm.get().as_bytes());
+    let constraints = CString::from_slice(constraints.as_bytes());
+    let r = InlineAsmCall(bcx,
+                          asm.as_ptr(),
+                          constraints.as_ptr(),
+                          inputs.as_slice(),
                           output_type,
                           ia.volatile,
                           ia.alignstack,
-                          dialect)
-        })
-    });
+                          dialect);
 
     // Again, based on how many outputs we have
     if num_outputs == 1 {
index 518042cf70889f71e4ca59b07a0f4e55caec1c40..d9c397d0c159ef6fb85b532cdf51631c299b50ef 100644 (file)
 
 use arena::TypedArena;
 use libc::{c_uint, uint64_t};
-use std::c_str::ToCStr;
+use std::ffi::{mod, CString};
 use std::cell::{Cell, RefCell};
 use std::collections::HashSet;
 use std::mem;
 use std::rc::Rc;
+use std::str;
 use std::{i8, i16, i32, i64};
 use syntax::abi::{Rust, RustCall, RustIntrinsic, Abi};
 use syntax::ast_util::local_def;
@@ -187,11 +188,10 @@ fn drop(&mut self) {
 pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
                ty: Type, output: ty::FnOutput) -> ValueRef {
 
-    let llfn: ValueRef = name.with_c_str(|buf| {
-        unsafe {
-            llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf, ty.to_ref())
-        }
-    });
+    let buf = CString::from_slice(name.as_bytes());
+    let llfn: ValueRef = unsafe {
+        llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf.as_ptr(), ty.to_ref())
+    };
 
     // diverging functions may unwind, but can never return normally
     if output == ty::FnDiverging {
@@ -334,9 +334,8 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId,
         None => ()
     }
     unsafe {
-        let c = name.with_c_str(|buf| {
-            llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf)
-        });
+        let buf = CString::from_slice(name.as_bytes());
+        let c = llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf.as_ptr());
         // Thread-local statics in some other crate need to *always* be linked
         // against in a thread-local fashion, so we need to be sure to apply the
         // thread-local attribute locally if it was present remotely. If we
@@ -475,15 +474,17 @@ pub fn set_always_inline(f: ValueRef) {
 }
 
 pub fn set_split_stack(f: ValueRef) {
-    "split-stack".with_c_str(|buf| {
-        unsafe { llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint, buf); }
-    })
+    unsafe {
+        llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint,
+                                        "split-stack\0".as_ptr() as *const _);
+    }
 }
 
 pub fn unset_split_stack(f: ValueRef) {
-    "split-stack".with_c_str(|buf| {
-        unsafe { llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint, buf); }
-    })
+    unsafe {
+        llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint,
+                                           "split-stack\0".as_ptr() as *const _);
+    }
 }
 
 // Double-check that we never ask LLVM to declare the same symbol twice. It
@@ -537,11 +538,8 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 // Structural comparison: a rather involved form of glue.
 pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
     if cx.sess().opts.cg.save_temps {
-        s.with_c_str(|buf| {
-            unsafe {
-                llvm::LLVMSetValueName(v, buf)
-            }
-        })
+        let buf = CString::from_slice(s.as_bytes());
+        unsafe { llvm::LLVMSetValueName(v, buf.as_ptr()) }
     }
 }
 
@@ -2645,11 +2643,10 @@ fn create_entry_fn(ccx: &CrateContext,
             unsafe { llvm::LLVMRustSetDLLExportStorageClass(llfn) }
         }
 
-        let llbb = "top".with_c_str(|buf| {
-            unsafe {
-                llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn, buf)
-            }
-        });
+        let llbb = unsafe {
+            llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn,
+                                                "top\0".as_ptr() as *const _)
+        };
         let bld = ccx.raw_builder();
         unsafe {
             llvm::LLVMPositionBuilderAtEnd(bld, llbb);
@@ -2670,9 +2667,9 @@ fn create_entry_fn(ccx: &CrateContext,
                 };
 
                 let args = {
-                    let opaque_rust_main = "rust_main".with_c_str(|buf| {
-                        llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p(ccx).to_ref(), buf)
-                    });
+                    let opaque_rust_main = llvm::LLVMBuildPointerCast(bld,
+                        rust_main, Type::i8p(ccx).to_ref(),
+                        "rust_main\0".as_ptr() as *const _);
 
                     vec!(
                         opaque_rust_main,
@@ -2779,9 +2776,9 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                                 format!("Illegal null byte in export_name \
                                          value: `{}`", sym)[]);
                         }
-                        let g = sym.with_c_str(|buf| {
-                            llvm::LLVMAddGlobal(ccx.llmod(), llty, buf)
-                        });
+                        let buf = CString::from_slice(sym.as_bytes());
+                        let g = llvm::LLVMAddGlobal(ccx.llmod(), llty,
+                                                    buf.as_ptr());
 
                         if attr::contains_name(i.attrs[],
                                                "thread_local") {
@@ -2823,9 +2820,8 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                                                  sect.get())[]);
                     }
                     unsafe {
-                        sect.get().with_c_str(|buf| {
-                            llvm::LLVMSetSection(v, buf);
-                        })
+                        let buf = CString::from_slice(sect.get().as_bytes());
+                        llvm::LLVMSetSection(v, buf.as_ptr());
                     }
                 },
                 None => ()
@@ -2992,17 +2988,16 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
     let name = format!("rust_metadata_{}_{}",
                        cx.link_meta().crate_name,
                        cx.link_meta().crate_hash);
-    let llglobal = name.with_c_str(|buf| {
-        unsafe {
-            llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(), buf)
-        }
-    });
+    let buf = CString::from_vec(name.into_bytes());
+    let llglobal = unsafe {
+        llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(),
+                            buf.as_ptr())
+    };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
         let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx);
-        name.with_c_str(|buf| {
-            llvm::LLVMSetSection(llglobal, buf)
-        });
+        let name = CString::from_slice(name.as_bytes());
+        llvm::LLVMSetSection(llglobal, name.as_ptr())
     }
     return metadata;
 }
@@ -3010,8 +3005,6 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
 /// Find any symbols that are defined in one compilation unit, but not declared
 /// in any other compilation unit.  Give these symbols internal linkage.
 fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
-    use std::c_str::CString;
-
     unsafe {
         let mut declared = HashSet::new();
 
@@ -3041,7 +3034,8 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
                     continue
                 }
 
-                let name = CString::new(llvm::LLVMGetValueName(val), false);
+                let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
+                               .to_vec();
                 declared.insert(name);
             }
         }
@@ -3057,9 +3051,10 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
                     continue
                 }
 
-                let name = CString::new(llvm::LLVMGetValueName(val), false);
+                let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
+                               .to_vec();
                 if !declared.contains(&name) &&
-                   !reachable.contains(name.as_str().unwrap()) {
+                   !reachable.contains(str::from_utf8(name.as_slice()).unwrap()) {
                     llvm::SetLinkage(val, llvm::InternalLinkage);
                 }
             }
index 97f0b92a290f839ab9871f6819dce94038bef53f..e09d36ddae923188be8407e9942c2aac077713ec 100644 (file)
@@ -20,7 +20,8 @@
 use trans::type_::Type;
 use util::nodemap::FnvHashMap;
 use libc::{c_uint, c_char};
-use std::c_str::ToCStr;
+
+use std::ffi::CString;
 use syntax::codemap::Span;
 
 pub struct Builder<'a, 'tcx: 'a> {
@@ -429,9 +430,9 @@ pub fn alloca(&self, ty: Type, name: &str) -> ValueRef {
             if name.is_empty() {
                 llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
             } else {
-                name.with_c_str(|c| {
-                    llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), c)
-                })
+                let name = CString::from_slice(name.as_bytes());
+                llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(),
+                                      name.as_ptr())
             }
         }
     }
@@ -774,12 +775,12 @@ pub fn add_comment(&self, text: &str) {
             let comment_text = format!("{} {}", "#",
                                        sanitized.replace("\n", "\n\t# "));
             self.count_insn("inlineasm");
-            let asm = comment_text.with_c_str(|c| {
-                unsafe {
-                    llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
-                                             c, noname(), False, False)
-                }
-            });
+            let comment_text = CString::from_vec(comment_text.into_bytes());
+            let asm = unsafe {
+                llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
+                                         comment_text.as_ptr(), noname(), False,
+                                         False)
+            };
             self.call(asm, &[], None);
         }
     }
@@ -926,9 +927,8 @@ pub fn trap(&self) {
             let bb: BasicBlockRef = llvm::LLVMGetInsertBlock(self.llbuilder);
             let fn_: ValueRef = llvm::LLVMGetBasicBlockParent(bb);
             let m: ModuleRef = llvm::LLVMGetGlobalParent(fn_);
-            let t: ValueRef = "llvm.trap".with_c_str(|buf| {
-                llvm::LLVMGetNamedFunction(m, buf)
-            });
+            let p = "llvm.trap\0".as_ptr();
+            let t: ValueRef = llvm::LLVMGetNamedFunction(m, p as *const _);
             assert!((t as int != 0));
             let args: &[ValueRef] = &[];
             self.count_insn("trap");
index e8dee19ed54c1f7acb82f645b2e3574391d211d0..094f98e988aad202fda3fc3e9535f62c1a3cdcaa 100644 (file)
@@ -44,7 +44,7 @@
 
 use arena::TypedArena;
 use libc::{c_uint, c_char};
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::cell::{Cell, RefCell};
 use std::vec::Vec;
 use syntax::ast::Ident;
@@ -401,9 +401,8 @@ pub fn get_llreturn(&self) -> BasicBlockRef {
         if self.llreturn.get().is_none() {
 
             self.llreturn.set(Some(unsafe {
-                "return".with_c_str(|buf| {
-                    llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn, buf)
-                })
+                llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn,
+                                                    "return\0".as_ptr() as *const _)
             }))
         }
 
@@ -429,11 +428,10 @@ pub fn new_block(&'a self,
                      opt_node_id: Option<ast::NodeId>)
                      -> Block<'a, 'tcx> {
         unsafe {
-            let llbb = name.with_c_str(|buf| {
-                    llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
-                                                        self.llfn,
-                                                        buf)
-                });
+            let name = CString::from_slice(name.as_bytes());
+            let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
+                                                           self.llfn,
+                                                           name.as_ptr());
             BlockS::new(llbb, is_lpad, opt_node_id, self)
         }
     }
@@ -708,7 +706,8 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
 
 pub fn C_floating(s: &str, t: Type) -> ValueRef {
     unsafe {
-        s.with_c_str(|buf| llvm::LLVMConstRealOfString(t.to_ref(), buf))
+        let s = CString::from_slice(s.as_bytes());
+        llvm::LLVMConstRealOfString(t.to_ref(), s.as_ptr())
     }
 }
 
@@ -789,9 +788,8 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
                                                 !null_terminated as Bool);
 
         let gsym = token::gensym("str");
-        let g = format!("str{}", gsym.uint()).with_c_str(|buf| {
-            llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf)
-        });
+        let buf = CString::from_vec(format!("str{}", gsym.uint()).into_bytes());
+        let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
         llvm::LLVMSetInitializer(g, sc);
         llvm::LLVMSetGlobalConstant(g, True);
         llvm::SetLinkage(g, llvm::InternalLinkage);
@@ -815,9 +813,10 @@ pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
         let lldata = C_bytes(cx, data);
 
         let gsym = token::gensym("binary");
-        let g = format!("binary{}", gsym.uint()).with_c_str(|buf| {
-            llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(), buf)
-        });
+        let name = format!("binary{}", gsym.uint());
+        let name = CString::from_vec(name.into_bytes());
+        let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(),
+                                    name.as_ptr());
         llvm::LLVMSetInitializer(g, lldata);
         llvm::LLVMSetGlobalConstant(g, True);
         llvm::SetLinkage(g, llvm::InternalLinkage);
index b17e852d7cbc44e7408e9107a0ebea6c81321880..9432fa8bd3d5983af8f26066f860779e8e98048a 100644 (file)
@@ -24,7 +24,6 @@
 use middle::ty::{self, Ty};
 use util::ppaux::{Repr, ty_to_string};
 
-use std::c_str::ToCStr;
 use std::iter::repeat;
 use libc::c_uint;
 use syntax::{ast, ast_util};
@@ -103,9 +102,8 @@ fn const_vec(cx: &CrateContext, e: &ast::Expr,
 
 pub fn const_addr_of(cx: &CrateContext, cv: ValueRef, mutbl: ast::Mutability) -> ValueRef {
     unsafe {
-        let gv = "const".with_c_str(|name| {
-            llvm::LLVMAddGlobal(cx.llmod(), val_ty(cv).to_ref(), name)
-        });
+        let gv = llvm::LLVMAddGlobal(cx.llmod(), val_ty(cv).to_ref(),
+                                     "const\0".as_ptr() as *const _);
         llvm::LLVMSetInitializer(gv, cv);
         llvm::LLVMSetGlobalConstant(gv,
                                     if mutbl == ast::MutImmutable {True} else {False});
index e5a0e2e9234d5ed1b022736dabc0f7e57abe243e..f974a6faf4c19d8e6feb31b7e4cda3417e86a312 100644 (file)
@@ -29,8 +29,8 @@
 use util::sha2::Sha256;
 use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
 
+use std::ffi::CString;
 use std::cell::{Cell, RefCell};
-use std::c_str::ToCStr;
 use std::ptr;
 use std::rc::Rc;
 use syntax::ast;
@@ -221,21 +221,16 @@ fn next(&mut self) -> Option<(CrateContext<'a, 'tcx>, bool)> {
 
 unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
     let llcx = llvm::LLVMContextCreate();
-    let llmod = mod_name.with_c_str(|buf| {
-        llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
-    });
-    sess.target
-        .target
-        .data_layout
-        .with_c_str(|buf| {
-        llvm::LLVMSetDataLayout(llmod, buf);
-    });
-    sess.target
-        .target
-        .llvm_target
-        .with_c_str(|buf| {
-        llvm::LLVMRustSetNormalizedTarget(llmod, buf);
-    });
+    let mod_name = CString::from_slice(mod_name.as_bytes());
+    let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
+
+    let data_layout = sess.target.target.data_layout.as_slice();
+    let data_layout = CString::from_slice(data_layout.as_bytes());
+    llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
+
+    let llvm_target = sess.target.target.llvm_target.as_slice();
+    let llvm_target = CString::from_slice(llvm_target.as_bytes());
+    llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
     (llcx, llmod)
 }
 
index 916fcbfe13ef77df022583d3acf82788b4ee20ee..a55953a882f037761cf2d7283d5c14e46d64e503 100644 (file)
 use util::ppaux;
 
 use libc::c_uint;
-use std::c_str::{CString, ToCStr};
+use std::ffi::CString;
 use std::cell::{Cell, RefCell};
 use std::ptr;
 use std::rc::{Rc, Weak};
@@ -760,14 +760,15 @@ pub fn finalize(cx: &CrateContext) {
         // for OS X to understand. For more info see #11352
         // This can be overridden using --llvm-opts -dwarf-version,N.
         if cx.sess().target.target.options.is_like_osx {
-            "Dwarf Version".with_c_str(
-                |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s, 2));
+            llvm::LLVMRustAddModuleFlag(cx.llmod(),
+                                        "Dwarf Version\0".as_ptr() as *const _,
+                                        2)
         }
 
         // Prevent bitcode readers from deleting the debug info.
-        "Debug Info Version".with_c_str(
-            |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s,
-                                            llvm::LLVMRustDebugMetadataVersion));
+        let ptr = "Debug Info Version\0".as_ptr();
+        llvm::LLVMRustAddModuleFlag(cx.llmod(), ptr as *const _,
+                                    llvm::LLVMRustDebugMetadataVersion);
     };
 }
 
@@ -829,22 +830,20 @@ pub fn create_global_var_metadata(cx: &CrateContext,
         namespace_node.mangled_name_of_contained_item(var_name[]);
     let var_scope = namespace_node.scope;
 
-    var_name.with_c_str(|var_name| {
-        linkage_name.with_c_str(|linkage_name| {
-            unsafe {
-                llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
-                                                        var_scope,
-                                                        var_name,
-                                                        linkage_name,
-                                                        file_metadata,
-                                                        line_number,
-                                                        type_metadata,
-                                                        is_local_to_unit,
-                                                        global,
-                                                        ptr::null_mut());
-            }
-        })
-    });
+    let var_name = CString::from_slice(var_name.as_bytes());
+    let linkage_name = CString::from_slice(linkage_name.as_bytes());
+    unsafe {
+        llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
+                                                var_scope,
+                                                var_name.as_ptr(),
+                                                linkage_name.as_ptr(),
+                                                file_metadata,
+                                                line_number,
+                                                type_metadata,
+                                                is_local_to_unit,
+                                                global,
+                                                ptr::null_mut());
+    }
 }
 
 /// Creates debug information for the given local variable.
@@ -1388,28 +1387,26 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
 
-    let fn_metadata = function_name.with_c_str(|function_name| {
-                          linkage_name.with_c_str(|linkage_name| {
-            unsafe {
-                llvm::LLVMDIBuilderCreateFunction(
-                    DIB(cx),
-                    containing_scope,
-                    function_name,
-                    linkage_name,
-                    file_metadata,
-                    loc.line as c_uint,
-                    function_type_metadata,
-                    is_local_to_unit,
-                    true,
-                    scope_line as c_uint,
-                    FlagPrototyped as c_uint,
-                    cx.sess().opts.optimize != config::No,
-                    llfn,
-                    template_parameters,
-                    ptr::null_mut())
-            }
-        })
-    });
+    let function_name = CString::from_slice(function_name.as_bytes());
+    let linkage_name = CString::from_slice(linkage_name.as_bytes());
+    let fn_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateFunction(
+            DIB(cx),
+            containing_scope,
+            function_name.as_ptr(),
+            linkage_name.as_ptr(),
+            file_metadata,
+            loc.line as c_uint,
+            function_type_metadata,
+            is_local_to_unit,
+            true,
+            scope_line as c_uint,
+            FlagPrototyped as c_uint,
+            cx.sess().opts.optimize != config::No,
+            llfn,
+            template_parameters,
+            ptr::null_mut())
+    };
 
     let scope_map = create_scope_map(cx,
                                      fn_decl.inputs.as_slice(),
@@ -1514,19 +1511,18 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
                 let ident = special_idents::type_self;
 
-                let param_metadata = token::get_ident(ident).get()
-                                                            .with_c_str(|name| {
-                    unsafe {
-                        llvm::LLVMDIBuilderCreateTemplateTypeParameter(
-                            DIB(cx),
-                            file_metadata,
-                            name,
-                            actual_self_type_metadata,
-                            ptr::null_mut(),
-                            0,
-                            0)
-                    }
-                });
+                let ident = token::get_ident(ident);
+                let name = CString::from_slice(ident.get().as_bytes());
+                let param_metadata = unsafe {
+                    llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+                        DIB(cx),
+                        file_metadata,
+                        name.as_ptr(),
+                        actual_self_type_metadata,
+                        ptr::null_mut(),
+                        0,
+                        0)
+                };
 
                 template_params.push(param_metadata);
             }
@@ -1549,19 +1545,18 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             // Again, only create type information if full debuginfo is enabled
             if cx.sess().opts.debuginfo == FullDebugInfo {
                 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
-                let param_metadata = token::get_ident(ident).get()
-                                                            .with_c_str(|name| {
-                    unsafe {
-                        llvm::LLVMDIBuilderCreateTemplateTypeParameter(
-                            DIB(cx),
-                            file_metadata,
-                            name,
-                            actual_type_metadata,
-                            ptr::null_mut(),
-                            0,
-                            0)
-                    }
-                });
+                let ident = token::get_ident(ident);
+                let name = CString::from_slice(ident.get().as_bytes());
+                let param_metadata = unsafe {
+                    llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+                        DIB(cx),
+                        file_metadata,
+                        name.as_ptr(),
+                        actual_type_metadata,
+                        ptr::null_mut(),
+                        0,
+                        0)
+                };
                 template_params.push(param_metadata);
             }
         }
@@ -1606,19 +1601,19 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
             } else {
                 match abs_path.path_relative_from(work_dir) {
                     Some(ref p) if p.is_relative() => {
-                            // prepend "./" if necessary
-                            let dotdot = b"..";
-                            let prefix = [dotdot[0], ::std::path::SEP_BYTE];
-                            let mut path_bytes = p.as_vec().to_vec();
-
-                            if path_bytes.slice_to(2) != prefix &&
-                               path_bytes.slice_to(2) != dotdot {
-                                path_bytes.insert(0, prefix[0]);
-                                path_bytes.insert(1, prefix[1]);
-                            }
-
-                            path_bytes.to_c_str()
+                        // prepend "./" if necessary
+                        let dotdot = b"..";
+                        let prefix: &[u8] = &[dotdot[0], ::std::path::SEP_BYTE];
+                        let mut path_bytes = p.as_vec().to_vec();
+
+                        if path_bytes.slice_to(2) != prefix &&
+                           path_bytes.slice_to(2) != dotdot {
+                            path_bytes.insert(0, prefix[0]);
+                            path_bytes.insert(1, prefix[1]);
                         }
+
+                        CString::from_vec(path_bytes)
+                    }
                     _ => fallback_path(cx)
                 }
             }
@@ -1630,29 +1625,25 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
                            (option_env!("CFG_VERSION")).expect("CFG_VERSION"));
 
     let compile_unit_name = compile_unit_name.as_ptr();
-    return work_dir.as_vec().with_c_str(|work_dir| {
-        producer.with_c_str(|producer| {
-            "".with_c_str(|flags| {
-                "".with_c_str(|split_name| {
-                    unsafe {
-                        llvm::LLVMDIBuilderCreateCompileUnit(
-                            debug_context(cx).builder,
-                            DW_LANG_RUST,
-                            compile_unit_name,
-                            work_dir,
-                            producer,
-                            cx.sess().opts.optimize != config::No,
-                            flags,
-                            0,
-                            split_name)
-                    }
-                })
-            })
-        })
-    });
+    let work_dir = CString::from_slice(work_dir.as_vec());
+    let producer = CString::from_slice(producer.as_bytes());
+    let flags = "\0";
+    let split_name = "\0";
+    return unsafe {
+        llvm::LLVMDIBuilderCreateCompileUnit(
+            debug_context(cx).builder,
+            DW_LANG_RUST,
+            compile_unit_name,
+            work_dir.as_ptr(),
+            producer.as_ptr(),
+            cx.sess().opts.optimize != config::No,
+            flags.as_ptr() as *const _,
+            0,
+            split_name.as_ptr() as *const _)
+    };
 
     fn fallback_path(cx: &CrateContext) -> CString {
-        cx.link_meta().crate_name.to_c_str()
+        CString::from_slice(cx.link_meta().crate_name.as_bytes())
     }
 }
 
@@ -1678,42 +1669,41 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         CapturedVariable => (0, DW_TAG_auto_variable)
     };
 
-    let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
-        match variable_access {
-            DirectVariable { alloca } => (
-                alloca,
-                unsafe {
-                    llvm::LLVMDIBuilderCreateLocalVariable(
-                        DIB(cx),
-                        dwarf_tag,
-                        scope_metadata,
-                        name,
-                        file_metadata,
-                        loc.line as c_uint,
-                        type_metadata,
-                        cx.sess().opts.optimize != config::No,
-                        0,
-                        argument_index)
-                }
-            ),
-            IndirectVariable { alloca, address_operations } => (
-                alloca,
-                unsafe {
-                    llvm::LLVMDIBuilderCreateComplexVariable(
-                        DIB(cx),
-                        dwarf_tag,
-                        scope_metadata,
-                        name,
-                        file_metadata,
-                        loc.line as c_uint,
-                        type_metadata,
-                        address_operations.as_ptr(),
-                        address_operations.len() as c_uint,
-                        argument_index)
-                }
-            )
-        }
-    });
+    let name = CString::from_slice(name.get().as_bytes());
+    let (var_alloca, var_metadata) = match variable_access {
+        DirectVariable { alloca } => (
+            alloca,
+            unsafe {
+                llvm::LLVMDIBuilderCreateLocalVariable(
+                    DIB(cx),
+                    dwarf_tag,
+                    scope_metadata,
+                    name.as_ptr(),
+                    file_metadata,
+                    loc.line as c_uint,
+                    type_metadata,
+                    cx.sess().opts.optimize != config::No,
+                    0,
+                    argument_index)
+            }
+        ),
+        IndirectVariable { alloca, address_operations } => (
+            alloca,
+            unsafe {
+                llvm::LLVMDIBuilderCreateComplexVariable(
+                    DIB(cx),
+                    dwarf_tag,
+                    scope_metadata,
+                    name.as_ptr(),
+                    file_metadata,
+                    loc.line as c_uint,
+                    type_metadata,
+                    address_operations.as_ptr(),
+                    address_operations.len() as c_uint,
+                    argument_index)
+            }
+        )
+    };
 
     set_debug_location(cx, DebugLocation::new(scope_metadata,
                                               loc.line,
@@ -1758,14 +1748,12 @@ fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
             full_path
         };
 
-    let file_metadata =
-        file_name.with_c_str(|file_name| {
-            work_dir.with_c_str(|work_dir| {
-                unsafe {
-                    llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
-                }
-            })
-        });
+    let file_name = CString::from_slice(file_name.as_bytes());
+    let work_dir = CString::from_slice(work_dir.as_bytes());
+    let file_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
+                                      work_dir.as_ptr())
+    };
 
     let mut created_files = debug_context(cx).created_files.borrow_mut();
     created_files.insert(full_path.to_string(), file_metadata);
@@ -1793,16 +1781,14 @@ fn scope_metadata(fcx: &FunctionContext,
 }
 
 fn diverging_type_metadata(cx: &CrateContext) -> DIType {
-    "!".with_c_str(|name| {
-        unsafe {
-            llvm::LLVMDIBuilderCreateBasicType(
-                DIB(cx),
-                name,
-                bytes_to_bits(0),
-                bytes_to_bits(0),
-                DW_ATE_unsigned)
-        }
-    })
+    unsafe {
+        llvm::LLVMDIBuilderCreateBasicType(
+            DIB(cx),
+            "!\0".as_ptr() as *const _,
+            bytes_to_bits(0),
+            bytes_to_bits(0),
+            DW_ATE_unsigned)
+    }
 }
 
 fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
@@ -1838,16 +1824,15 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     let llvm_type = type_of::type_of(cx, t);
     let (size, align) = size_and_align_of(cx, llvm_type);
-    let ty_metadata = name.with_c_str(|name| {
-        unsafe {
-            llvm::LLVMDIBuilderCreateBasicType(
-                DIB(cx),
-                name,
-                bytes_to_bits(size),
-                bytes_to_bits(align),
-                encoding)
-        }
-    });
+    let name = CString::from_slice(name.as_bytes());
+    let ty_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateBasicType(
+            DIB(cx),
+            name.as_ptr(),
+            bytes_to_bits(size),
+            bytes_to_bits(align),
+            encoding)
+    };
 
     return ty_metadata;
 }
@@ -1859,16 +1844,15 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let pointer_llvm_type = type_of::type_of(cx, pointer_type);
     let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
     let name = compute_debuginfo_type_name(cx, pointer_type, false);
-    let ptr_metadata = name.with_c_str(|name| {
-        unsafe {
-            llvm::LLVMDIBuilderCreatePointerType(
-                DIB(cx),
-                pointee_type_metadata,
-                bytes_to_bits(pointer_size),
-                bytes_to_bits(pointer_align),
-                name)
-        }
-    });
+    let name = CString::from_slice(name.as_bytes());
+    let ptr_metadata = unsafe {
+        llvm::LLVMDIBuilderCreatePointerType(
+            DIB(cx),
+            pointee_type_metadata,
+            bytes_to_bits(pointer_size),
+            bytes_to_bits(pointer_align),
+            name.as_ptr())
+    };
     return ptr_metadata;
 }
 
@@ -2478,14 +2462,14 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let enumerators_metadata: Vec<DIDescriptor> = variants
         .iter()
         .map(|v| {
-            token::get_name(v.name).get().with_c_str(|name| {
-                unsafe {
-                    llvm::LLVMDIBuilderCreateEnumerator(
-                        DIB(cx),
-                        name,
-                        v.disr_val as u64)
-                }
-            })
+            let token = token::get_name(v.name);
+            let name = CString::from_slice(token.get().as_bytes());
+            unsafe {
+                llvm::LLVMDIBuilderCreateEnumerator(
+                    DIB(cx),
+                    name.as_ptr(),
+                    v.disr_val as u64)
+            }
         })
         .collect();
 
@@ -2509,20 +2493,19 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                   codemap::DUMMY_SP);
                 let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
 
-                let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| {
-                    unsafe {
-                        llvm::LLVMDIBuilderCreateEnumerationType(
-                            DIB(cx),
-                            containing_scope,
-                            name,
-                            UNKNOWN_FILE_METADATA,
-                            UNKNOWN_LINE_NUMBER,
-                            bytes_to_bits(discriminant_size),
-                            bytes_to_bits(discriminant_align),
-                            create_DIArray(DIB(cx), enumerators_metadata[]),
-                            discriminant_base_type_metadata)
-                    }
-                });
+                let name = CString::from_slice(discriminant_name.get().as_bytes());
+                let discriminant_type_metadata = unsafe {
+                    llvm::LLVMDIBuilderCreateEnumerationType(
+                        DIB(cx),
+                        containing_scope,
+                        name.as_ptr(),
+                        UNKNOWN_FILE_METADATA,
+                        UNKNOWN_LINE_NUMBER,
+                        bytes_to_bits(discriminant_size),
+                        bytes_to_bits(discriminant_align),
+                        create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
+                        discriminant_base_type_metadata)
+                };
 
                 debug_context(cx).created_enum_disr_types
                                  .borrow_mut()
@@ -2553,24 +2536,22 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                              .borrow()
                              .get_unique_type_id_as_string(unique_type_id);
 
-    let enum_metadata = enum_name.with_c_str(|enum_name| {
-        unique_type_id_str.with_c_str(|unique_type_id_str| {
-            unsafe {
-                llvm::LLVMDIBuilderCreateUnionType(
-                DIB(cx),
-                containing_scope,
-                enum_name,
-                UNKNOWN_FILE_METADATA,
-                UNKNOWN_LINE_NUMBER,
-                bytes_to_bits(enum_type_size),
-                bytes_to_bits(enum_type_align),
-                0, // Flags
-                ptr::null_mut(),
-                0, // RuntimeLang
-                unique_type_id_str)
-            }
-        })
-    });
+    let enum_name = CString::from_slice(enum_name.as_bytes());
+    let unique_type_id_str = CString::from_slice(unique_type_id_str.as_bytes());
+    let enum_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateUnionType(
+        DIB(cx),
+        containing_scope,
+        enum_name.as_ptr(),
+        UNKNOWN_FILE_METADATA,
+        UNKNOWN_LINE_NUMBER,
+        bytes_to_bits(enum_type_size),
+        bytes_to_bits(enum_type_align),
+        0, // Flags
+        ptr::null_mut(),
+        0, // RuntimeLang
+        unique_type_id_str.as_ptr())
+    };
 
     return create_and_register_recursive_type_forward_declaration(
         cx,
@@ -2681,21 +2662,20 @@ fn set_members_of_composite_type(cx: &CrateContext,
                 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
             };
 
-            member_description.name.with_c_str(|member_name| {
-                unsafe {
-                    llvm::LLVMDIBuilderCreateMemberType(
-                        DIB(cx),
-                        composite_type_metadata,
-                        member_name,
-                        UNKNOWN_FILE_METADATA,
-                        UNKNOWN_LINE_NUMBER,
-                        bytes_to_bits(member_size),
-                        bytes_to_bits(member_align),
-                        bytes_to_bits(member_offset),
-                        member_description.flags,
-                        member_description.type_metadata)
-                }
-            })
+            let member_name = CString::from_slice(member_description.name.as_bytes());
+            unsafe {
+                llvm::LLVMDIBuilderCreateMemberType(
+                    DIB(cx),
+                    composite_type_metadata,
+                    member_name.as_ptr(),
+                    UNKNOWN_FILE_METADATA,
+                    UNKNOWN_LINE_NUMBER,
+                    bytes_to_bits(member_size),
+                    bytes_to_bits(member_align),
+                    bytes_to_bits(member_offset),
+                    member_description.flags,
+                    member_description.type_metadata)
+            }
         })
         .collect();
 
@@ -2719,30 +2699,28 @@ fn create_struct_stub(cx: &CrateContext,
     let unique_type_id_str = debug_context(cx).type_map
                                               .borrow()
                                               .get_unique_type_id_as_string(unique_type_id);
+    let name = CString::from_slice(struct_type_name.as_bytes());
+    let unique_type_id = CString::from_slice(unique_type_id_str.as_bytes());
     let metadata_stub = unsafe {
-        struct_type_name.with_c_str(|name| {
-            unique_type_id_str.with_c_str(|unique_type_id| {
-                // LLVMDIBuilderCreateStructType() wants an empty array. A null
-                // pointer will lead to hard to trace and debug LLVM assertions
-                // later on in llvm/lib/IR/Value.cpp.
-                let empty_array = create_DIArray(DIB(cx), &[]);
-
-                llvm::LLVMDIBuilderCreateStructType(
-                    DIB(cx),
-                    containing_scope,
-                    name,
-                    UNKNOWN_FILE_METADATA,
-                    UNKNOWN_LINE_NUMBER,
-                    bytes_to_bits(struct_size),
-                    bytes_to_bits(struct_align),
-                    0,
-                    ptr::null_mut(),
-                    empty_array,
-                    0,
-                    ptr::null_mut(),
-                    unique_type_id)
-            })
-        })
+        // LLVMDIBuilderCreateStructType() wants an empty array. A null
+        // pointer will lead to hard to trace and debug LLVM assertions
+        // later on in llvm/lib/IR/Value.cpp.
+        let empty_array = create_DIArray(DIB(cx), &[]);
+
+        llvm::LLVMDIBuilderCreateStructType(
+            DIB(cx),
+            containing_scope,
+            name.as_ptr(),
+            UNKNOWN_FILE_METADATA,
+            UNKNOWN_LINE_NUMBER,
+            bytes_to_bits(struct_size),
+            bytes_to_bits(struct_align),
+            0,
+            ptr::null_mut(),
+            empty_array,
+            0,
+            ptr::null_mut(),
+            unique_type_id.as_ptr())
     };
 
     return metadata_stub;
@@ -4079,18 +4057,18 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTree
                         None => ptr::null_mut()
                     };
                     let namespace_name = token::get_name(name);
-                    let scope = namespace_name.get().with_c_str(|namespace_name| {
-                        unsafe {
-                            llvm::LLVMDIBuilderCreateNameSpace(
-                                DIB(cx),
-                                parent_scope,
-                                namespace_name,
-                                // cannot reconstruct file ...
-                                ptr::null_mut(),
-                                // ... or line information, but that's not so important.
-                                0)
-                        }
-                    });
+                    let namespace_name = CString::from_slice(namespace_name
+                                                                .get().as_bytes());
+                    let scope = unsafe {
+                        llvm::LLVMDIBuilderCreateNameSpace(
+                            DIB(cx),
+                            parent_scope,
+                            namespace_name.as_ptr(),
+                            // cannot reconstruct file ...
+                            ptr::null_mut(),
+                            // ... or line information, but that's not so important.
+                            0)
+                    };
 
                     let node = Rc::new(NamespaceTreeNode {
                         name: name,
@@ -4128,7 +4106,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTree
 /// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
 pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
     if needs_gdb_debug_scripts_section(ccx) {
-        let empty = b"".to_c_str();
+        let empty = CString::from_slice(b"");
         let gdb_debug_scripts_section_global =
             get_or_insert_gdb_debug_scripts_section_global(ccx);
         unsafe {
@@ -4145,14 +4123,15 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext)
 /// section.
 fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
                                                   -> llvm::ValueRef {
-    let section_var_name = b"__rustc_debug_gdb_scripts_section__".to_c_str();
+    let section_var_name = b"__rustc_debug_gdb_scripts_section__\0";
 
     let section_var = unsafe {
-        llvm::LLVMGetNamedGlobal(ccx.llmod(), section_var_name.as_ptr())
+        llvm::LLVMGetNamedGlobal(ccx.llmod(),
+                                 section_var_name.as_ptr() as *const _)
     };
 
     if section_var == ptr::null_mut() {
-        let section_name = b".debug_gdb_scripts".to_c_str();
+        let section_name = b".debug_gdb_scripts\0";
         let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
 
         unsafe {
@@ -4160,8 +4139,9 @@ fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
                                         section_contents.len() as u64);
             let section_var = llvm::LLVMAddGlobal(ccx.llmod(),
                                                   llvm_type.to_ref(),
-                                                  section_var_name.as_ptr());
-            llvm::LLVMSetSection(section_var, section_name.as_ptr());
+                                                  section_var_name.as_ptr()
+                                                    as *const _);
+            llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
             llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
             llvm::LLVMSetGlobalConstant(section_var, llvm::True);
             llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
index a4cfec791d8172e5fa32385e83eac4fa7f98cdd3..1c9be6ae4a8ba5e357566cf1ff2d65834ac56020 100644 (file)
 use trans::type_of::*;
 use trans::type_of;
 use middle::ty::{self, Ty};
-use middle::subst::{Substs};
+use middle::subst::Substs;
+
+use std::ffi::CString;
 use std::cmp;
-use std::c_str::ToCStr;
 use libc::c_uint;
 use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi};
 use syntax::abi::{RustIntrinsic, Rust, RustCall, Stdcall, Fastcall, System};
@@ -132,9 +133,9 @@ pub fn register_static(ccx: &CrateContext,
             };
             unsafe {
                 // Declare a symbol `foo` with the desired linkage.
-                let g1 = ident.get().with_c_str(|buf| {
-                    llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(), buf)
-                });
+                let buf = CString::from_slice(ident.get().as_bytes());
+                let g1 = llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(),
+                                             buf.as_ptr());
                 llvm::SetLinkage(g1, linkage);
 
                 // Declare an internal global `extern_with_linkage_foo` which
@@ -145,9 +146,9 @@ pub fn register_static(ccx: &CrateContext,
                 // zero.
                 let mut real_name = "_rust_extern_with_linkage_".to_string();
                 real_name.push_str(ident.get());
-                let g2 = real_name.with_c_str(|buf| {
-                    llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf)
-                });
+                let real_name = CString::from_vec(real_name.into_bytes());
+                let g2 = llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(),
+                                             real_name.as_ptr());
                 llvm::SetLinkage(g2, llvm::InternalLinkage);
                 llvm::LLVMSetInitializer(g2, g1);
                 g2
@@ -155,9 +156,8 @@ pub fn register_static(ccx: &CrateContext,
         }
         None => unsafe {
             // Generate an external declaration.
-            ident.get().with_c_str(|buf| {
-                llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf)
-            })
+            let buf = CString::from_slice(ident.get().as_bytes());
+            llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf.as_ptr())
         }
     }
 }
@@ -606,9 +606,9 @@ unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         //         return r;
         //     }
 
-        let the_block =
-            "the block".with_c_str(
-                |s| llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn, s));
+        let ptr = "the block\0".as_ptr();
+        let the_block = llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn,
+                                                            ptr as *const _);
 
         let builder = ccx.builder();
         builder.position_at_end(the_block);
index c049704181354d9c8b1f91323be55e10c73d149f..2525220c57021ee0c157bc5d00465731911f6d2f 100644 (file)
@@ -40,8 +40,8 @@
 use util::ppaux;
 
 use arena::TypedArena;
-use std::c_str::ToCStr;
 use libc::c_uint;
+use std::ffi::CString;
 use syntax::ast;
 use syntax::parse::token;
 
@@ -498,11 +498,11 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
     let llalign = llalign_of(ccx, llty);
     let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc");
     debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name);
-    let gvar = name.with_c_str(|buf| {
-        unsafe {
-            llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(), buf)
-        }
-    });
+    let buf = CString::from_slice(name.as_bytes());
+    let gvar = unsafe {
+        llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(),
+                            buf.as_ptr())
+    };
     note_unique_llvm_symbol(ccx, name);
 
     let ty_name = token::intern_and_get_ident(
index c13516134c20c7988a940899f429e17a95a44189..dec4524e676654785f618b7bf11bf5c9e826dde3 100644 (file)
@@ -34,7 +34,7 @@
 use middle::ty::MethodCall;
 use util::ppaux::Repr;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::rc::Rc;
 use syntax::abi::{Rust, RustCall};
 use syntax::parse::token;
@@ -742,9 +742,9 @@ pub fn make_vtable<I: Iterator<Item=ValueRef>>(ccx: &CrateContext,
     unsafe {
         let tbl = C_struct(ccx, components[], false);
         let sym = token::gensym("vtable");
-        let vt_gvar = format!("vtable{}", sym.uint()).with_c_str(|buf| {
-            llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(), buf)
-        });
+        let buf = CString::from_vec(format!("vtable{}", sym.uint()).into_bytes());
+        let vt_gvar = llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(),
+                                          buf.as_ptr());
         llvm::LLVMSetInitializer(vt_gvar, tbl);
         llvm::LLVMSetGlobalConstant(vt_gvar, llvm::True);
         llvm::SetLinkage(vt_gvar, llvm::InternalLinkage);
index 5b76f5bb8270e77b12f76f81cf664a3cb8aec423..3785c2fb9bc54e5b633e3dd36099266ed2840dec 100644 (file)
@@ -19,7 +19,7 @@
 
 use syntax::ast;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::mem;
 use std::cell::RefCell;
 use std::iter::repeat;
@@ -157,7 +157,8 @@ pub fn struct_(ccx: &CrateContext, els: &[Type], packed: bool) -> Type {
     }
 
     pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
-        ty!(name.with_c_str(|s| llvm::LLVMStructCreateNamed(ccx.llcx(), s)))
+        let name = CString::from_slice(name.as_bytes());
+        ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr()))
     }
 
     pub fn empty_struct(ccx: &CrateContext) -> Type {
index 0f0dbf6a24dffc7de58cbf2bdeb6a4fc18a8870c..dcc90117d26606041d1cc721e52e893706df9c8d 100644 (file)
@@ -20,8 +20,8 @@
 
 #[cfg(unix)]
 mod imp {
+    use std::ffi::CString;
     use libc;
-    use std::c_str::ToCStr;
 
     #[cfg(target_os = "linux")]
     mod os {
@@ -111,9 +111,11 @@ pub struct Lock {
 
     impl Lock {
         pub fn new(p: &Path) -> Lock {
-            let fd = p.with_c_str(|s| unsafe {
-                libc::open(s, libc::O_RDWR | libc::O_CREAT, libc::S_IRWXU)
-            });
+            let buf = CString::from_slice(p.as_vec());
+            let fd = unsafe {
+                libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
+                           libc::S_IRWXU)
+            };
             assert!(fd > 0);
             let flock = os::flock {
                 l_start: 0,
index 9d003eca27f3dd11ad067352adb3f048b85b0ac9..3b9265cf569765a39822fea60f54c567ddc9a46a 100644 (file)
@@ -29,7 +29,7 @@
 
 use libc;
 use std::ascii::AsciiExt;
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::cell::{RefCell, Cell};
 use std::collections::HashMap;
 use std::fmt;
@@ -215,7 +215,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
                 let id = id.as_ref().map(|a| a.as_slice());
                 s.push_str(highlight::highlight(text.as_slice(), None, id)
                                      .as_slice());
-                let output = s.to_c_str();
+                let output = CString::from_vec(s.into_bytes());
                 hoedown_buffer_puts(ob, output.as_ptr());
             })
         }
@@ -224,15 +224,16 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
     extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer,
                      level: libc::c_int, opaque: *mut libc::c_void) {
         // hoedown does this, we may as well too
-        "\n".with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) });
+        unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); }
 
         // Extract the text provided
         let s = if text.is_null() {
             "".to_string()
         } else {
-            unsafe {
-                String::from_raw_buf_len((*text).data, (*text).size as uint)
-            }
+            let s = unsafe {
+                slice::from_raw_buf(&(*text).data, (*text).size as uint)
+            };
+            str::from_utf8(s).unwrap().to_string()
         };
 
         // Transform the contents of the header into a hyphenated string
@@ -273,7 +274,8 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
                                format!("{} ", sec)
                            });
 
-        text.with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) });
+        let text = CString::from_vec(text.into_bytes());
+        unsafe { hoedown_buffer_puts(ob, text.as_ptr()) }
     }
 
     reset_headers();
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
deleted file mode 100644 (file)
index 9c96a9c..0000000
+++ /dev/null
@@ -1,857 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! C-string manipulation and management
-//!
-//! This modules provides the basic methods for creating and manipulating
-//! null-terminated strings for use with FFI calls (back to C). Most C APIs require
-//! that the string being passed to them is null-terminated, and by default rust's
-//! string types are *not* null terminated.
-//!
-//! The other problem with translating Rust strings to C strings is that Rust
-//! strings can validly contain a null-byte in the middle of the string (0 is a
-//! valid Unicode codepoint). This means that not all Rust strings can actually be
-//! translated to C strings.
-//!
-//! # Creation of a C string
-//!
-//! A C string is managed through the `CString` type defined in this module. It
-//! "owns" the internal buffer of characters and will automatically deallocate the
-//! buffer when the string is dropped. The `ToCStr` trait is implemented for `&str`
-//! and `&[u8]`, but the conversions can fail due to some of the limitations
-//! explained above.
-//!
-//! This also means that currently whenever a C string is created, an allocation
-//! must be performed to place the data elsewhere (the lifetime of the C string is
-//! not tied to the lifetime of the original string/data buffer). If C strings are
-//! heavily used in applications, then caching may be advisable to prevent
-//! unnecessary amounts of allocations.
-//!
-//! Be carefull to remember that the memory is managed by C allocator API and not
-//! by Rust allocator API.
-//! That means that the CString pointers should be freed with C allocator API
-//! if you intend to do that on your own, as the behaviour if you free them with
-//! Rust's allocator API is not well defined
-//!
-//! An example of creating and using a C string would be:
-//!
-//! ```rust
-//! extern crate libc;
-//!
-//! use std::c_str::ToCStr;
-//!
-//! extern {
-//!     fn puts(s: *const libc::c_char);
-//! }
-//!
-//! fn main() {
-//!     let my_string = "Hello, world!";
-//!
-//!     // Allocate the C string with an explicit local that owns the string. The
-//!     // `c_buffer` pointer will be deallocated when `my_c_string` goes out of scope.
-//!     let my_c_string = my_string.to_c_str();
-//!     unsafe {
-//!         puts(my_c_string.as_ptr());
-//!     }
-//!
-//!     // Don't save/return the pointer to the C string, the `c_buffer` will be
-//!     // deallocated when this block returns!
-//!     my_string.with_c_str(|c_buffer| {
-//!         unsafe { puts(c_buffer); }
-//!     });
-//! }
-//! ```
-
-use core::prelude::*;
-use libc;
-
-use cmp::Ordering;
-use fmt;
-use hash;
-use mem;
-use ptr;
-use slice::{self, IntSliceExt};
-use str;
-use string::String;
-use core::kinds::marker;
-
-/// The representation of a C String.
-///
-/// This structure wraps a `*libc::c_char`, and will automatically free the
-/// memory it is pointing to when it goes out of scope.
-#[allow(missing_copy_implementations)]
-pub struct CString {
-    buf: *const libc::c_char,
-    owns_buffer_: bool,
-}
-
-unsafe impl Send for CString { }
-unsafe impl Sync for CString { }
-
-impl Clone for CString {
-    /// Clone this CString into a new, uniquely owned CString. For safety
-    /// reasons, this is always a deep clone with the memory allocated
-    /// with C's allocator API, rather than the usual shallow clone.
-    fn clone(&self) -> CString {
-        let len = self.len() + 1;
-        let buf = unsafe { libc::malloc(len as libc::size_t) } as *mut libc::c_char;
-        if buf.is_null() { ::alloc::oom() }
-        unsafe { ptr::copy_nonoverlapping_memory(buf, self.buf, len); }
-        CString { buf: buf as *const libc::c_char, owns_buffer_: true }
-    }
-}
-
-impl PartialEq for CString {
-    fn eq(&self, other: &CString) -> bool {
-        // Check if the two strings share the same buffer
-        if self.buf as uint == other.buf as uint {
-            true
-        } else {
-            unsafe {
-                libc::strcmp(self.buf, other.buf) == 0
-            }
-        }
-    }
-}
-
-impl PartialOrd for CString {
-    #[inline]
-    fn partial_cmp(&self, other: &CString) -> Option<Ordering> {
-        self.as_bytes().partial_cmp(other.as_bytes())
-    }
-}
-
-impl Eq for CString {}
-
-impl<S: hash::Writer> hash::Hash<S> for CString {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.as_bytes().hash(state)
-    }
-}
-
-impl CString {
-    /// Create a C String from a pointer, with memory managed by C's allocator
-    /// API, so avoid calling it with a pointer to memory managed by Rust's
-    /// allocator API, as the behaviour would not be well defined.
-    ///
-    ///# Panics
-    ///
-    /// Panics if `buf` is null
-    pub unsafe fn new(buf: *const libc::c_char, owns_buffer: bool) -> CString {
-        assert!(!buf.is_null());
-        CString { buf: buf, owns_buffer_: owns_buffer }
-    }
-
-    /// Return a pointer to the NUL-terminated string data.
-    ///
-    /// `.as_ptr` returns an internal pointer into the `CString`, and
-    /// may be invalidated when the `CString` falls out of scope (the
-    /// destructor will run, freeing the allocation if there is
-    /// one).
-    ///
-    /// ```rust
-    /// use std::c_str::ToCStr;
-    ///
-    /// let foo = "some string";
-    ///
-    /// // right
-    /// let x = foo.to_c_str();
-    /// let p = x.as_ptr();
-    ///
-    /// // wrong (the CString will be freed, invalidating `p`)
-    /// let p = foo.to_c_str().as_ptr();
-    /// ```
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// extern crate libc;
-    ///
-    /// use std::c_str::ToCStr;
-    ///
-    /// fn main() {
-    ///     let c_str = "foo bar".to_c_str();
-    ///     unsafe {
-    ///         libc::puts(c_str.as_ptr());
-    ///     }
-    /// }
-    /// ```
-    pub fn as_ptr(&self) -> *const libc::c_char {
-        self.buf
-    }
-
-    /// Return a mutable pointer to the NUL-terminated string data.
-    ///
-    /// `.as_mut_ptr` returns an internal pointer into the `CString`, and
-    /// may be invalidated when the `CString` falls out of scope (the
-    /// destructor will run, freeing the allocation if there is
-    /// one).
-    ///
-    /// ```rust
-    /// use std::c_str::ToCStr;
-    ///
-    /// let foo = "some string";
-    ///
-    /// // right
-    /// let mut x = foo.to_c_str();
-    /// let p = x.as_mut_ptr();
-    ///
-    /// // wrong (the CString will be freed, invalidating `p`)
-    /// let p = foo.to_c_str().as_mut_ptr();
-    /// ```
-    pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
-        self.buf as *mut _
-    }
-
-    /// Returns whether or not the `CString` owns the buffer.
-    pub fn owns_buffer(&self) -> bool {
-        self.owns_buffer_
-    }
-
-    /// Converts the CString into a `&[u8]` without copying.
-    /// Includes the terminating NUL byte.
-    #[inline]
-    pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
-        unsafe {
-            slice::from_raw_buf(&self.buf, self.len() + 1).as_unsigned()
-        }
-    }
-
-    /// Converts the CString into a `&[u8]` without copying.
-    /// Does not include the terminating NUL byte.
-    #[inline]
-    pub fn as_bytes_no_nul<'a>(&'a self) -> &'a [u8] {
-        unsafe {
-            slice::from_raw_buf(&self.buf, self.len()).as_unsigned()
-        }
-    }
-
-    /// Converts the CString into a `&str` without copying.
-    /// Returns None if the CString is not UTF-8.
-    #[inline]
-    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
-        let buf = self.as_bytes_no_nul();
-        str::from_utf8(buf).ok()
-    }
-
-    /// Return a CString iterator.
-    pub fn iter<'a>(&'a self) -> CChars<'a> {
-        CChars {
-            ptr: self.buf,
-            marker: marker::ContravariantLifetime,
-        }
-    }
-
-    /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
-    ///
-    /// Any ownership of the buffer by the `CString` wrapper is
-    /// forgotten, meaning that the backing allocation of this
-    /// `CString` is not automatically freed if it owns the
-    /// allocation. In this case, a user of `.unwrap()` should ensure
-    /// the allocation is freed, to avoid leaking memory. You should
-    /// use libc's memory allocator in this case.
-    ///
-    /// Prefer `.as_ptr()` when just retrieving a pointer to the
-    /// string data, as that does not relinquish ownership.
-    pub unsafe fn into_inner(mut self) -> *const libc::c_char {
-        self.owns_buffer_ = false;
-        self.buf
-    }
-
-    /// Return the number of bytes in the CString (not including the NUL
-    /// terminator).
-    #[inline]
-    pub fn len(&self) -> uint {
-        unsafe { libc::strlen(self.buf) as uint }
-    }
-
-    /// Returns if there are no bytes in this string
-    #[inline]
-    pub fn is_empty(&self) -> bool { self.len() == 0 }
-}
-
-impl Drop for CString {
-    fn drop(&mut self) {
-        if self.owns_buffer_ {
-            unsafe {
-                libc::free(self.buf as *mut libc::c_void)
-            }
-        }
-    }
-}
-
-impl fmt::Show for CString {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        String::from_utf8_lossy(self.as_bytes_no_nul()).fmt(f)
-    }
-}
-
-/// A generic trait for converting a value to a CString.
-pub trait ToCStr for Sized? {
-    /// Copy the receiver into a CString.
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the receiver has an interior null.
-    fn to_c_str(&self) -> CString;
-
-    /// Unsafe variant of `to_c_str()` that doesn't check for nulls.
-    unsafe fn to_c_str_unchecked(&self) -> CString;
-
-    /// Work with a temporary CString constructed from the receiver.
-    /// The provided `*libc::c_char` will be freed immediately upon return.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// extern crate libc;
-    ///
-    /// use std::c_str::ToCStr;
-    ///
-    /// fn main() {
-    ///     let s = "PATH".with_c_str(|path| unsafe {
-    ///         libc::getenv(path)
-    ///     });
-    /// }
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the receiver has an interior null.
-    #[inline]
-    fn with_c_str<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        let c_str = self.to_c_str();
-        f(c_str.as_ptr())
-    }
-
-    /// Unsafe variant of `with_c_str()` that doesn't check for nulls.
-    #[inline]
-    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        let c_str = self.to_c_str_unchecked();
-        f(c_str.as_ptr())
-    }
-}
-
-impl ToCStr for str {
-    #[inline]
-    fn to_c_str(&self) -> CString {
-        self.as_bytes().to_c_str()
-    }
-
-    #[inline]
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        self.as_bytes().to_c_str_unchecked()
-    }
-
-    #[inline]
-    fn with_c_str<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        self.as_bytes().with_c_str(f)
-    }
-
-    #[inline]
-    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        self.as_bytes().with_c_str_unchecked(f)
-    }
-}
-
-impl ToCStr for String {
-    #[inline]
-    fn to_c_str(&self) -> CString {
-        self.as_bytes().to_c_str()
-    }
-
-    #[inline]
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        self.as_bytes().to_c_str_unchecked()
-    }
-
-    #[inline]
-    fn with_c_str<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        self.as_bytes().with_c_str(f)
-    }
-
-    #[inline]
-    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        self.as_bytes().with_c_str_unchecked(f)
-    }
-}
-
-// The length of the stack allocated buffer for `vec.with_c_str()`
-const BUF_LEN: uint = 128;
-
-impl ToCStr for [u8] {
-    fn to_c_str(&self) -> CString {
-        let mut cs = unsafe { self.to_c_str_unchecked() };
-        check_for_null(self, cs.as_mut_ptr());
-        cs
-    }
-
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        let self_len = self.len();
-        let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8;
-        if buf.is_null() { ::alloc::oom() }
-
-        ptr::copy_memory(buf, self.as_ptr(), self_len);
-        *buf.offset(self_len as int) = 0;
-
-        CString::new(buf as *const libc::c_char, true)
-    }
-
-    fn with_c_str<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        unsafe { with_c_str(self, true, f) }
-    }
-
-    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        with_c_str(self, false, f)
-    }
-}
-
-impl<'a, Sized? T: ToCStr> ToCStr for &'a T {
-    #[inline]
-    fn to_c_str(&self) -> CString {
-        (**self).to_c_str()
-    }
-
-    #[inline]
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        (**self).to_c_str_unchecked()
-    }
-
-    #[inline]
-    fn with_c_str<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        (**self).with_c_str(f)
-    }
-
-    #[inline]
-    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        (**self).with_c_str_unchecked(f)
-    }
-}
-
-// Unsafe function that handles possibly copying the &[u8] into a stack array.
-unsafe fn with_c_str<T, F>(v: &[u8], checked: bool, f: F) -> T where
-    F: FnOnce(*const libc::c_char) -> T,
-{
-    let c_str = if v.len() < BUF_LEN {
-        let mut buf: [u8; BUF_LEN] = mem::uninitialized();
-        slice::bytes::copy_memory(&mut buf, v);
-        buf[v.len()] = 0;
-
-        let buf = buf.as_mut_ptr();
-        if checked {
-            check_for_null(v, buf as *mut libc::c_char);
-        }
-
-        return f(buf as *const libc::c_char)
-    } else if checked {
-        v.to_c_str()
-    } else {
-        v.to_c_str_unchecked()
-    };
-
-    f(c_str.as_ptr())
-}
-
-#[inline]
-fn check_for_null(v: &[u8], buf: *mut libc::c_char) {
-    for i in range(0, v.len()) {
-        unsafe {
-            let p = buf.offset(i as int);
-            assert!(*p != 0);
-        }
-    }
-}
-
-/// External iterator for a CString's bytes.
-///
-/// Use with the `std::iter` module.
-#[allow(raw_pointer_deriving)]
-#[derive(Clone)]
-pub struct CChars<'a> {
-    ptr: *const libc::c_char,
-    marker: marker::ContravariantLifetime<'a>,
-}
-
-impl<'a> Iterator for CChars<'a> {
-    type Item = libc::c_char;
-
-    fn next(&mut self) -> Option<libc::c_char> {
-        let ch = unsafe { *self.ptr };
-        if ch == 0 {
-            None
-        } else {
-            self.ptr = unsafe { self.ptr.offset(1) };
-            Some(ch)
-        }
-    }
-}
-
-/// Parses a C "multistring", eg windows env values or
-/// the req->ptr result in a uv_fs_readdir() call.
-///
-/// Optionally, a `count` can be passed in, limiting the
-/// parsing to only being done `count`-times.
-///
-/// The specified closure is invoked with each string that
-/// is found, and the number of strings found is returned.
-pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char,
-                                    count: Option<uint>,
-                                    mut f: F)
-                                    -> uint where
-    F: FnMut(&CString),
-{
-
-    let mut curr_ptr: uint = buf as uint;
-    let mut ctr = 0;
-    let (limited_count, limit) = match count {
-        Some(limit) => (true, limit),
-        None => (false, 0)
-    };
-    while ((limited_count && ctr < limit) || !limited_count)
-          && *(curr_ptr as *const libc::c_char) != 0 as libc::c_char {
-        let cstr = CString::new(curr_ptr as *const libc::c_char, false);
-        f(&cstr);
-        curr_ptr += cstr.len() + 1;
-        ctr += 1;
-    }
-    return ctr;
-}
-
-#[cfg(test)]
-mod tests {
-    use prelude::v1::*;
-    use super::*;
-    use ptr;
-    use thread::Thread;
-    use libc;
-
-    #[test]
-    fn test_str_multistring_parsing() {
-        unsafe {
-            let input = b"zero\0one\0\0";
-            let ptr = input.as_ptr();
-            let expected = ["zero", "one"];
-            let mut it = expected.iter();
-            let result = from_c_multistring(ptr as *const libc::c_char, None, |c| {
-                let cbytes = c.as_bytes_no_nul();
-                assert_eq!(cbytes, it.next().unwrap().as_bytes());
-            });
-            assert_eq!(result, 2);
-            assert!(it.next().is_none());
-        }
-    }
-
-    #[test]
-    fn test_str_to_c_str() {
-        let c_str = "".to_c_str();
-        unsafe {
-            assert_eq!(*c_str.as_ptr().offset(0), 0);
-        }
-
-        let c_str = "hello".to_c_str();
-        let buf = c_str.as_ptr();
-        unsafe {
-            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
-            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
-            assert_eq!(*buf.offset(2), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(4), 'o' as libc::c_char);
-            assert_eq!(*buf.offset(5), 0);
-        }
-    }
-
-    #[test]
-    fn test_vec_to_c_str() {
-        let b: &[u8] = &[];
-        let c_str = b.to_c_str();
-        unsafe {
-            assert_eq!(*c_str.as_ptr().offset(0), 0);
-        }
-
-        let c_str = b"hello".to_c_str();
-        let buf = c_str.as_ptr();
-        unsafe {
-            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
-            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
-            assert_eq!(*buf.offset(2), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(4), 'o' as libc::c_char);
-            assert_eq!(*buf.offset(5), 0);
-        }
-
-        let c_str = b"foo\xFF".to_c_str();
-        let buf = c_str.as_ptr();
-        unsafe {
-            assert_eq!(*buf.offset(0), 'f' as libc::c_char);
-            assert_eq!(*buf.offset(1), 'o' as libc::c_char);
-            assert_eq!(*buf.offset(2), 'o' as libc::c_char);
-            assert_eq!(*buf.offset(3), 0xffu8 as libc::c_char);
-            assert_eq!(*buf.offset(4), 0);
-        }
-    }
-
-    #[test]
-    fn test_unwrap() {
-        let c_str = "hello".to_c_str();
-        unsafe { libc::free(c_str.into_inner() as *mut libc::c_void) }
-    }
-
-    #[test]
-    fn test_as_ptr() {
-        let c_str = "hello".to_c_str();
-        let len = unsafe { libc::strlen(c_str.as_ptr()) };
-        assert_eq!(len, 5);
-    }
-
-    #[test]
-    fn test_iterator() {
-        let c_str = "".to_c_str();
-        let mut iter = c_str.iter();
-        assert_eq!(iter.next(), None);
-
-        let c_str = "hello".to_c_str();
-        let mut iter = c_str.iter();
-        assert_eq!(iter.next(), Some('h' as libc::c_char));
-        assert_eq!(iter.next(), Some('e' as libc::c_char));
-        assert_eq!(iter.next(), Some('l' as libc::c_char));
-        assert_eq!(iter.next(), Some('l' as libc::c_char));
-        assert_eq!(iter.next(), Some('o' as libc::c_char));
-        assert_eq!(iter.next(), None);
-    }
-
-    #[test]
-    fn test_to_c_str_fail() {
-        assert!(Thread::spawn(move|| { "he\x00llo".to_c_str() }).join().is_err());
-    }
-
-    #[test]
-    fn test_to_c_str_unchecked() {
-        unsafe {
-            let c_string = "he\x00llo".to_c_str_unchecked();
-            let buf = c_string.as_ptr();
-            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
-            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
-            assert_eq!(*buf.offset(2), 0);
-            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(4), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(5), 'o' as libc::c_char);
-            assert_eq!(*buf.offset(6), 0);
-        }
-    }
-
-    #[test]
-    fn test_as_bytes() {
-        let c_str = "hello".to_c_str();
-        assert_eq!(c_str.as_bytes(), b"hello\0");
-        let c_str = "".to_c_str();
-        assert_eq!(c_str.as_bytes(), b"\0");
-        let c_str = b"foo\xFF".to_c_str();
-        assert_eq!(c_str.as_bytes(), b"foo\xFF\0");
-    }
-
-    #[test]
-    fn test_as_bytes_no_nul() {
-        let c_str = "hello".to_c_str();
-        assert_eq!(c_str.as_bytes_no_nul(), b"hello");
-        let c_str = "".to_c_str();
-        let exp: &[u8] = &[];
-        assert_eq!(c_str.as_bytes_no_nul(), exp);
-        let c_str = b"foo\xFF".to_c_str();
-        assert_eq!(c_str.as_bytes_no_nul(), b"foo\xFF");
-    }
-
-    #[test]
-    fn test_as_str() {
-        let c_str = "hello".to_c_str();
-        assert_eq!(c_str.as_str(), Some("hello"));
-        let c_str = "".to_c_str();
-        assert_eq!(c_str.as_str(), Some(""));
-        let c_str = b"foo\xFF".to_c_str();
-        assert_eq!(c_str.as_str(), None);
-    }
-
-    #[test]
-    #[should_fail]
-    fn test_new_fail() {
-        let _c_str = unsafe { CString::new(ptr::null(), false) };
-    }
-
-    #[test]
-    fn test_clone() {
-        let a = "hello".to_c_str();
-        let b = a.clone();
-        assert!(a == b);
-    }
-
-    #[test]
-    fn test_clone_noleak() {
-        fn foo<F>(f: F) where F: FnOnce(&CString) {
-            let s = "test".to_string();
-            let c = s.to_c_str();
-            // give the closure a non-owned CString
-            let mut c_ = unsafe { CString::new(c.as_ptr(), false) };
-            f(&c_);
-            // muck with the buffer for later printing
-            unsafe { *c_.as_mut_ptr() = 'X' as libc::c_char }
-        }
-
-        let mut c_: Option<CString> = None;
-        foo(|c| {
-            c_ = Some(c.clone());
-            c.clone();
-            // force a copy, reading the memory
-            c.as_bytes().to_vec();
-        });
-        let c_ = c_.unwrap();
-        // force a copy, reading the memory
-        c_.as_bytes().to_vec();
-    }
-}
-
-#[cfg(test)]
-mod bench {
-    extern crate test;
-
-    use prelude::v1::*;
-    use self::test::Bencher;
-    use libc;
-    use c_str::ToCStr;
-
-    #[inline]
-    fn check(s: &str, c_str: *const libc::c_char) {
-        let s_buf = s.as_ptr();
-        for i in range(0, s.len()) {
-            unsafe {
-                assert_eq!(
-                    *s_buf.offset(i as int) as libc::c_char,
-                    *c_str.offset(i as int));
-            }
-        }
-    }
-
-    static S_SHORT: &'static str = "Mary";
-    static S_MEDIUM: &'static str = "Mary had a little lamb";
-    static S_LONG: &'static str = "\
-        Mary had a little lamb, Little lamb
-        Mary had a little lamb, Little lamb
-        Mary had a little lamb, Little lamb
-        Mary had a little lamb, Little lamb
-        Mary had a little lamb, Little lamb
-        Mary had a little lamb, Little lamb";
-
-    fn bench_to_string(b: &mut Bencher, s: &str) {
-        b.iter(|| {
-            let c_str = s.to_c_str();
-            check(s, c_str.as_ptr());
-        })
-    }
-
-    #[bench]
-    fn bench_to_c_str_short(b: &mut Bencher) {
-        bench_to_string(b, S_SHORT)
-    }
-
-    #[bench]
-    fn bench_to_c_str_medium(b: &mut Bencher) {
-        bench_to_string(b, S_MEDIUM)
-    }
-
-    #[bench]
-    fn bench_to_c_str_long(b: &mut Bencher) {
-        bench_to_string(b, S_LONG)
-    }
-
-    fn bench_to_c_str_unchecked(b: &mut Bencher, s: &str) {
-        b.iter(|| {
-            let c_str = unsafe { s.to_c_str_unchecked() };
-            check(s, c_str.as_ptr())
-        })
-    }
-
-    #[bench]
-    fn bench_to_c_str_unchecked_short(b: &mut Bencher) {
-        bench_to_c_str_unchecked(b, S_SHORT)
-    }
-
-    #[bench]
-    fn bench_to_c_str_unchecked_medium(b: &mut Bencher) {
-        bench_to_c_str_unchecked(b, S_MEDIUM)
-    }
-
-    #[bench]
-    fn bench_to_c_str_unchecked_long(b: &mut Bencher) {
-        bench_to_c_str_unchecked(b, S_LONG)
-    }
-
-    fn bench_with_c_str(b: &mut Bencher, s: &str) {
-        b.iter(|| {
-            s.with_c_str(|c_str_buf| check(s, c_str_buf))
-        })
-    }
-
-    #[bench]
-    fn bench_with_c_str_short(b: &mut Bencher) {
-        bench_with_c_str(b, S_SHORT)
-    }
-
-    #[bench]
-    fn bench_with_c_str_medium(b: &mut Bencher) {
-        bench_with_c_str(b, S_MEDIUM)
-    }
-
-    #[bench]
-    fn bench_with_c_str_long(b: &mut Bencher) {
-        bench_with_c_str(b, S_LONG)
-    }
-
-    fn bench_with_c_str_unchecked(b: &mut Bencher, s: &str) {
-        b.iter(|| {
-            unsafe {
-                s.with_c_str_unchecked(|c_str_buf| check(s, c_str_buf))
-            }
-        })
-    }
-
-    #[bench]
-    fn bench_with_c_str_unchecked_short(b: &mut Bencher) {
-        bench_with_c_str_unchecked(b, S_SHORT)
-    }
-
-    #[bench]
-    fn bench_with_c_str_unchecked_medium(b: &mut Bencher) {
-        bench_with_c_str_unchecked(b, S_MEDIUM)
-    }
-
-    #[bench]
-    fn bench_with_c_str_unchecked_long(b: &mut Bencher) {
-        bench_with_c_str_unchecked(b, S_LONG)
-    }
-}
diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs
deleted file mode 100644 (file)
index 4a20208..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Library to interface with chunks of memory allocated in C.
-//!
-//! It is often desirable to safely interface with memory allocated from C,
-//! encapsulating the unsafety into allocation and destruction time.  Indeed,
-//! allocating memory externally is currently the only way to give Rust shared
-//! mut state with C programs that keep their own references; vectors are
-//! unsuitable because they could be reallocated or moved at any time, and
-//! importing C memory into a vector takes a one-time snapshot of the memory.
-//!
-//! This module simplifies the usage of such external blocks of memory.  Memory
-//! is encapsulated into an opaque object after creation; the lifecycle of the
-//! memory can be optionally managed by Rust, if an appropriate destructor
-//! closure is provided.  Safety is ensured by bounds-checking accesses, which
-//! are marshalled through get and set functions.
-//!
-//! There are three unsafe functions: the two constructors, and the
-//! unwrap method. The constructors are unsafe for the
-//! obvious reason (they act on a pointer that cannot be checked inside the
-//! method), but `unwrap()` is somewhat more subtle in its unsafety.
-//! It returns the contained pointer, but at the same time destroys the CVec
-//! without running its destructor. This can be used to pass memory back to
-//! C, but care must be taken that the ownership of underlying resources are
-//! handled correctly, i.e. that allocated memory is eventually freed
-//! if necessary.
-
-#![experimental]
-
-use kinds::Send;
-use mem;
-use ops::{Drop, FnOnce};
-use option::Option;
-use option::Option::{Some, None};
-use ptr::PtrExt;
-use ptr;
-use raw;
-use slice::AsSlice;
-use thunk::{Thunk};
-
-/// The type representing a foreign chunk of memory
-pub struct CVec<T> {
-    base: *mut T,
-    len: uint,
-    dtor: Option<Thunk>,
-}
-
-#[unsafe_destructor]
-impl<T> Drop for CVec<T> {
-    fn drop(&mut self) {
-        match self.dtor.take() {
-            None => (),
-            Some(f) => f.invoke(())
-        }
-    }
-}
-
-impl<T> CVec<T> {
-    /// Create a `CVec` from a raw pointer to a buffer with a given length.
-    ///
-    /// Panics if the given pointer is null. The returned vector will not attempt
-    /// to deallocate the vector when dropped.
-    ///
-    /// # Arguments
-    ///
-    /// * base - A raw pointer to a buffer
-    /// * len - The number of elements in the buffer
-    pub unsafe fn new(base: *mut T, len: uint) -> CVec<T> {
-        assert!(base != ptr::null_mut());
-        CVec {
-            base: base,
-            len: len,
-            dtor: None,
-        }
-    }
-
-    /// Create a `CVec` from a foreign buffer, with a given length,
-    /// and a function to run upon destruction.
-    ///
-    /// Panics if the given pointer is null.
-    ///
-    /// # Arguments
-    ///
-    /// * base - A foreign pointer to a buffer
-    /// * len - The number of elements in the buffer
-    /// * dtor - A fn to run when the value is destructed, useful
-    ///          for freeing the buffer, etc.
-    pub unsafe fn new_with_dtor<F>(base: *mut T,
-                                   len: uint,
-                                   dtor: F)
-                                   -> CVec<T>
-        where F : FnOnce(), F : Send
-    {
-        assert!(base != ptr::null_mut());
-        let dtor: Thunk = Thunk::new(dtor);
-        CVec {
-            base: base,
-            len: len,
-            dtor: Some(dtor)
-        }
-    }
-
-    /// View the stored data as a mutable slice.
-    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
-        unsafe {
-            mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
-        }
-    }
-
-    /// Retrieves an element at a given index, returning `None` if the requested
-    /// index is greater than the length of the vector.
-    pub fn get<'a>(&'a self, ofs: uint) -> Option<&'a T> {
-        if ofs < self.len {
-            Some(unsafe { &*self.base.offset(ofs as int) })
-        } else {
-            None
-        }
-    }
-
-    /// Retrieves a mutable element at a given index, returning `None` if the
-    /// requested index is greater than the length of the vector.
-    pub fn get_mut<'a>(&'a mut self, ofs: uint) -> Option<&'a mut T> {
-        if ofs < self.len {
-            Some(unsafe { &mut *self.base.offset(ofs as int) })
-        } else {
-            None
-        }
-    }
-
-    /// Unwrap the pointer without running the destructor
-    ///
-    /// This method retrieves the underlying pointer, and in the process
-    /// destroys the CVec but without running the destructor. A use case
-    /// would be transferring ownership of the buffer to a C function, as
-    /// in this case you would not want to run the destructor.
-    ///
-    /// Note that if you want to access the underlying pointer without
-    /// cancelling the destructor, you can simply call `transmute` on the return
-    /// value of `get(0)`.
-    pub unsafe fn into_inner(mut self) -> *mut T {
-        self.dtor = None;
-        self.base
-    }
-
-    /// Returns the number of items in this vector.
-    pub fn len(&self) -> uint { self.len }
-
-    /// Returns whether this vector is empty.
-    pub fn is_empty(&self) -> bool { self.len() == 0 }
-}
-
-impl<T> AsSlice<T> for CVec<T> {
-    /// View the stored data as a slice.
-    fn as_slice<'a>(&'a self) -> &'a [T] {
-        unsafe {
-            mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use prelude::v1::*;
-
-    use super::CVec;
-    use libc;
-    use ptr;
-
-    fn malloc(n: uint) -> CVec<u8> {
-        unsafe {
-            let mem = ptr::Unique(libc::malloc(n as libc::size_t));
-            if mem.0.is_null() { ::alloc::oom() }
-
-            CVec::new_with_dtor(mem.0 as *mut u8,
-                                n,
-                                move|| { libc::free(mem.0 as *mut libc::c_void); })
-        }
-    }
-
-    #[test]
-    fn test_basic() {
-        let mut cv = malloc(16);
-
-        *cv.get_mut(3).unwrap() = 8;
-        *cv.get_mut(4).unwrap() = 9;
-        assert_eq!(*cv.get(3).unwrap(), 8);
-        assert_eq!(*cv.get(4).unwrap(), 9);
-        assert_eq!(cv.len(), 16);
-    }
-
-    #[test]
-    #[should_fail]
-    fn test_panic_at_null() {
-        unsafe {
-            CVec::new(ptr::null_mut::<u8>(), 9);
-        }
-    }
-
-    #[test]
-    fn test_overrun_get() {
-        let cv = malloc(16);
-
-        assert!(cv.get(17).is_none());
-    }
-
-    #[test]
-    fn test_overrun_set() {
-        let mut cv = malloc(16);
-
-        assert!(cv.get_mut(17).is_none());
-    }
-
-    #[test]
-    fn test_unwrap() {
-        unsafe {
-            let cv = CVec::new_with_dtor(1 as *mut int,
-                                         0,
-                                         move|:| panic!("Don't run this destructor!"));
-            let p = cv.into_inner();
-            assert_eq!(p, 1 as *mut int);
-        }
-    }
-
-}
index de3d75ffb324202c49001b202a2eee40b852c4a1..66cb1f2c948d9ff28dc0c2fca7cf9c88f2daf13b 100644 (file)
@@ -17,7 +17,7 @@
 
 use prelude::v1::*;
 
-use c_str::ToCStr;
+use ffi::CString;
 use mem;
 use os;
 use str;
@@ -51,13 +51,11 @@ impl DynamicLibrary {
 
     /// Lazily open a dynamic library. When passed None it gives a
     /// handle to the calling process
-    pub fn open<T: ToCStr>(filename: Option<T>)
-                        -> Result<DynamicLibrary, String> {
+    pub fn open(filename: Option<&Path>) -> Result<DynamicLibrary, String> {
         unsafe {
-            let mut filename = filename;
             let maybe_library = dl::check_for_errors_in(|| {
-                match filename.take() {
-                    Some(name) => dl::open_external(name),
+                match filename {
+                    Some(name) => dl::open_external(name.as_vec()),
                     None => dl::open_internal()
                 }
             });
@@ -131,9 +129,8 @@ pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*mut T, String> {
         // T but that feature is still unimplemented
 
         let maybe_symbol_value = dl::check_for_errors_in(|| {
-            symbol.with_c_str(|raw_string| {
-                dl::symbol(self.handle, raw_string)
-            })
+            let raw_string = CString::from_slice(symbol.as_bytes());
+            dl::symbol(self.handle, raw_string.as_ptr())
         });
 
         // The value must not be constructed if there is an error so
@@ -157,7 +154,7 @@ mod test {
     fn test_loading_cosine() {
         // The math library does not need to be loaded since it is already
         // statically linked in
-        let none: Option<Path> = None; // appease the typechecker
+        let none: Option<&Path> = None; // appease the typechecker
         let libm = match DynamicLibrary::open(none) {
             Err(error) => panic!("Could not load self as module: {}", error),
             Ok(libm) => libm
@@ -202,17 +199,17 @@ fn test_errors_do_not_crash() {
           target_os = "freebsd",
           target_os = "dragonfly"))]
 pub mod dl {
-    use self::Rtld::*;
-
+    pub use self::Rtld::*;
     use prelude::v1::*;
-    use c_str::{CString, ToCStr};
+
+    use ffi::{self, CString};
+    use str;
     use libc;
     use ptr;
 
-    pub unsafe fn open_external<T: ToCStr>(filename: T) -> *mut u8 {
-        filename.with_c_str(|raw_name| {
-            dlopen(raw_name, Lazy as libc::c_int) as *mut u8
-        })
+    pub unsafe fn open_external(filename: &[u8]) -> *mut u8 {
+        let s = CString::from_slice(filename);
+        dlopen(s.as_ptr(), Lazy as libc::c_int) as *mut u8
     }
 
     pub unsafe fn open_internal() -> *mut u8 {
@@ -236,8 +233,8 @@ pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
             let ret = if ptr::null() == last_error {
                 Ok(result)
             } else {
-                Err(String::from_str(CString::new(last_error, false).as_str()
-                    .unwrap()))
+                let s = ffi::c_str_to_bytes(&last_error);
+                Err(str::from_utf8(s).unwrap().to_string())
             };
 
             ret
@@ -273,7 +270,6 @@ fn dlsym(handle: *mut libc::c_void,
 
 #[cfg(target_os = "windows")]
 pub mod dl {
-    use c_str::ToCStr;
     use iter::IteratorExt;
     use libc;
     use ops::FnOnce;
@@ -287,10 +283,9 @@ pub mod dl {
     use string::String;
     use vec::Vec;
 
-    pub unsafe fn open_external<T: ToCStr>(filename: T) -> *mut u8 {
+    pub unsafe fn open_external(filename: &[u8]) -> *mut u8 {
         // Windows expects Unicode data
-        let filename_cstr = filename.to_c_str();
-        let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
+        let filename_str = str::from_utf8(filename).unwrap();
         let mut filename_str: Vec<u16> = filename_str.utf16_units().collect();
         filename_str.push(0);
         LoadLibraryW(filename_str.as_ptr() as *const libc::c_void) as *mut u8
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
new file mode 100644 (file)
index 0000000..bef2344
--- /dev/null
@@ -0,0 +1,218 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use fmt;
+use iter::IteratorExt;
+use libc;
+use mem;
+use ops::Deref;
+use slice::{self, SliceExt, AsSlice};
+use string::String;
+use vec::Vec;
+
+/// A type representing a C-compatible string
+///
+/// This type serves the primary purpose of being able to generate a
+/// C-compatible string from a Rust byte slice or vector. An instance of this
+/// type is a static guarantee that the underlying bytes contain no interior 0
+/// bytes and the final byte is 0.
+///
+/// A `CString` is created from either a byte slice or a byte vector. After
+/// being created, a `CString` predominately inherits all of its methods from
+/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
+/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
+/// `u8` slice can be obtained with the `as_bytes` method.  Slices produced from
+/// a `CString` do *not* contain the trailing nul terminator unless otherwise
+/// specified.
+///
+/// # Example
+///
+/// ```no_run
+/// # extern crate libc;
+/// # fn main() {
+/// use std::ffi::CString;
+/// use libc;
+///
+/// extern {
+///     fn my_printer(s: *const libc::c_char);
+/// }
+///
+/// let to_print = "Hello, world!";
+/// let c_to_print = CString::from_slice(to_print.as_bytes());
+/// unsafe {
+///     my_printer(c_to_print.as_ptr());
+/// }
+/// # }
+/// ```
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+pub struct CString {
+    inner: Vec<libc::c_char>,
+}
+
+impl CString {
+    /// Create a new C-compatible string from a byte slice.
+    ///
+    /// This method will copy the data of the slice provided into a new
+    /// allocation, ensuring that there is a trailing 0 byte.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if there are any 0 bytes already in the slice
+    /// provided.
+    pub fn from_slice(v: &[u8]) -> CString {
+        CString::from_vec(v.to_vec())
+    }
+
+    /// Create a C-compatible string from a byte vector.
+    ///
+    /// This method will consume ownership of the provided vector, appending a 0
+    /// byte to the end after verifying that there are no interior 0 bytes.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if there are any 0 bytes already in the vector
+    /// provided.
+    pub fn from_vec(v: Vec<u8>) -> CString {
+        assert!(!v.iter().any(|&x| x == 0));
+        unsafe { CString::from_vec_unchecked(v) }
+    }
+
+    /// Create a C-compatibel string from a byte vector without checking for
+    /// interior 0 bytes.
+    ///
+    /// This method is equivalent to `from_vec` except that no runtime assertion
+    /// is made that `v` contains no 0 bytes.
+    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
+        v.push(0);
+        CString { inner: mem::transmute(v) }
+    }
+
+    /// Create a view into this C string which includes the trailing nul
+    /// terminator at the end of the string.
+    pub fn as_slice_with_nul(&self) -> &[libc::c_char] { self.inner.as_slice() }
+
+    /// Similar to the `as_slice` method, but returns a `u8` slice instead of a
+    /// `libc::c_char` slice.
+    pub fn as_bytes(&self) -> &[u8] {
+        unsafe { mem::transmute(self.as_slice()) }
+    }
+
+    /// Equivalend to `as_slice_with_nul` except that the type returned is a
+    /// `u8` slice instead of a `libc::c_char` slice.
+    pub fn as_bytes_with_nul(&self) -> &[u8] {
+        unsafe { mem::transmute(self.as_slice_with_nul()) }
+    }
+}
+
+impl Deref for CString {
+    type Target = [libc::c_char];
+
+    fn deref(&self) -> &[libc::c_char] {
+        self.inner.slice_to(self.inner.len() - 1)
+    }
+}
+
+impl fmt::Show for CString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        String::from_utf8_lossy(self.as_bytes()).fmt(f)
+    }
+}
+
+/// Interpret a C string as a byte slice.
+///
+/// This function will calculate the length of the C string provided, and it
+/// will then return a corresponding slice for the contents of the C string not
+/// including the nul terminator.
+///
+/// This function will tie the lifetime of the returned slice to the lifetime of
+/// the pointer provided. This is done to help prevent the slice from escaping
+/// the lifetime of the pointer itself. If a longer lifetime is needed, then
+/// `mem::copy_lifetime` should be used.
+///
+/// This function is unsafe because there is no guarantee of the validity of the
+/// pointer `raw` or a guarantee that a nul terminator will be found.
+///
+/// # Example
+///
+/// ```no_run
+/// # extern crate libc;
+/// # fn main() {
+/// use std::ffi;
+/// use std::str;
+/// use libc;
+///
+/// extern {
+///     fn my_string() -> *const libc::c_char;
+/// }
+///
+/// unsafe {
+///     let to_print = my_string();
+///     let slice = ffi::c_str_to_bytes(&to_print);
+///     println!("string returned: {}", str::from_utf8(slice).unwrap());
+/// }
+/// # }
+/// ```
+pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
+    let len = libc::strlen(*raw);
+    slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
+}
+
+/// Interpret a C string as a byte slice with the nul terminator.
+///
+/// This function is identical to `from_raw_buf` except that the returned slice
+/// will include the nul terminator of the string.
+pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
+    let len = libc::strlen(*raw) + 1;
+    slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::v1::*;
+    use super::*;
+    use libc;
+    use mem;
+
+    #[test]
+    fn c_to_rust() {
+        let data = b"123\0";
+        let ptr = data.as_ptr() as *const libc::c_char;
+        unsafe {
+            assert_eq!(c_str_to_bytes(&ptr), b"123");
+            assert_eq!(c_str_to_bytes_with_nul(&ptr), b"123\0");
+        }
+    }
+
+    #[test]
+    fn simple() {
+        let s = CString::from_slice(b"1234");
+        assert_eq!(s.as_bytes(), b"1234");
+        assert_eq!(s.as_bytes_with_nul(), b"1234\0");
+        unsafe {
+            assert_eq!(s.as_slice(),
+                       mem::transmute::<_, &[libc::c_char]>(b"1234"));
+            assert_eq!(s.as_slice_with_nul(),
+                       mem::transmute::<_, &[libc::c_char]>(b"1234\0"));
+        }
+    }
+
+    #[should_fail] #[test]
+    fn build_with_zero1() { CString::from_slice(b"\0"); }
+    #[should_fail] #[test]
+    fn build_with_zero2() { CString::from_vec(vec![0]); }
+
+    #[test]
+    fn build_with_zero3() {
+        unsafe {
+            let s = CString::from_vec_unchecked(vec![0]);
+            assert_eq!(s.as_bytes(), b"\0");
+        }
+    }
+}
diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
new file mode 100644 (file)
index 0000000..cc86f80
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Utilities related to FFI bindings.
+
+#![unstable = "module just underwent fairly large reorganization and the dust \
+               still needs to settle"]
+
+pub use self::c_str::CString;
+pub use self::c_str::c_str_to_bytes;
+pub use self::c_str::c_str_to_bytes_with_nul;
+
+mod c_str;
index daefdd28b306a5c7264154e567ea18ee28e6fccd..738c70412f78a0aa3def5993a313879ecdeed747 100644 (file)
@@ -22,7 +22,8 @@
 
 use prelude::v1::*;
 
-use c_str::ToCStr;
+use ffi::CString;
+use path::BytesContainer;
 use io::{Listener, Acceptor, IoResult, TimedOut, standard_error};
 use sys::pipe::UnixAcceptor as UnixAcceptorImp;
 use sys::pipe::UnixListener as UnixListenerImp;
@@ -53,8 +54,9 @@ impl UnixStream {
     /// let mut stream = UnixStream::connect(&server);
     /// stream.write(&[1, 2, 3]);
     /// ```
-    pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
-        UnixStreamImp::connect(&path.to_c_str(), None)
+    pub fn connect<P: BytesContainer>(path: P) -> IoResult<UnixStream> {
+        let path = CString::from_slice(path.container_as_bytes());
+        UnixStreamImp::connect(&path, None)
             .map(|inner| UnixStream { inner: inner })
     }
 
@@ -67,13 +69,15 @@ pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
     /// If a `timeout` with zero or negative duration is specified then
     /// the function returns `Err`, with the error kind set to `TimedOut`.
     #[experimental = "the timeout argument is likely to change types"]
-    pub fn connect_timeout<P: ToCStr>(path: &P,
-                                      timeout: Duration) -> IoResult<UnixStream> {
+    pub fn connect_timeout<P>(path: P, timeout: Duration)
+                              -> IoResult<UnixStream>
+                              where P: BytesContainer {
         if timeout <= Duration::milliseconds(0) {
             return Err(standard_error(TimedOut));
         }
 
-        UnixStreamImp::connect(&path.to_c_str(), Some(timeout.num_milliseconds() as u64))
+        let path = CString::from_slice(path.container_as_bytes());
+        UnixStreamImp::connect(&path, Some(timeout.num_milliseconds() as u64))
             .map(|inner| UnixStream { inner: inner })
     }
 
@@ -177,8 +181,9 @@ impl UnixListener {
     /// }
     /// # }
     /// ```
-    pub fn bind<P: ToCStr>(path: &P) -> IoResult<UnixListener> {
-        UnixListenerImp::bind(&path.to_c_str())
+    pub fn bind<P: BytesContainer>(path: P) -> IoResult<UnixListener> {
+        let path = CString::from_slice(path.container_as_bytes());
+        UnixListenerImp::bind(&path)
             .map(|inner| UnixListener { inner: inner })
     }
 }
index 5886c9cc3e287cce773223efc80ef48546860fb6..ea232ad0c3f1b0876b1d860fb1dd1447397b7d1f 100644 (file)
@@ -18,8 +18,8 @@
 
 use prelude::v1::*;
 
-use c_str::{CString, ToCStr};
 use collections::HashMap;
+use ffi::CString;
 use fmt;
 use hash::Hash;
 use io::pipe::{PipeStream, PipePair};
@@ -35,6 +35,7 @@
 use thread::Thread;
 
 #[cfg(windows)] use std::hash::sip::SipState;
+#[cfg(windows)] use str;
 
 /// Signal a process to exit, without forcibly killing it. Corresponds to
 /// SIGTERM on unix platforms.
@@ -109,11 +110,11 @@ pub struct Process {
 impl Hash for EnvKey {
     fn hash(&self, state: &mut SipState) {
         let &EnvKey(ref x) = self;
-        match x.as_str() {
-            Some(s) => for ch in s.chars() {
+        match str::from_utf8(x.as_bytes()) {
+            Ok(s) => for ch in s.chars() {
                 (ch as u8 as char).to_lowercase().hash(state);
             },
-            None => x.hash(state)
+            Err(..) => x.hash(state)
         }
     }
 }
@@ -123,8 +124,8 @@ impl PartialEq for EnvKey {
     fn eq(&self, other: &EnvKey) -> bool {
         let &EnvKey(ref x) = self;
         let &EnvKey(ref y) = other;
-        match (x.as_str(), y.as_str()) {
-            (Some(xs), Some(ys)) => {
+        match (str::from_utf8(x.as_bytes()), str::from_utf8(y.as_bytes())) {
+            (Ok(xs), Ok(ys)) => {
                 if xs.len() != ys.len() {
                     return false
                 } else {
@@ -185,10 +186,10 @@ pub struct Command {
 }
 
 // FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
+// we cannot usefully take BytesContainer arguments by reference (without forcing an
 // additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
+// for &Path, so that we can take BytesContainer as owned. When DST lands, the &Path
+// instance should be removed, and arguments bound by BytesContainer should be passed by
 // reference. (Here: {new, arg, args, env}.)
 
 impl Command {
@@ -203,9 +204,9 @@ impl Command {
     ///
     /// Builder methods are provided to change these defaults and
     /// otherwise configure the process.
-    pub fn new<T:ToCStr>(program: T) -> Command {
+    pub fn new<T: BytesContainer>(program: T) -> Command {
         Command {
-            program: program.to_c_str(),
+            program: CString::from_slice(program.container_as_bytes()),
             args: Vec::new(),
             env: None,
             cwd: None,
@@ -219,27 +220,29 @@ pub fn new<T:ToCStr>(program: T) -> Command {
     }
 
     /// Add an argument to pass to the program.
-    pub fn arg<'a, T: ToCStr>(&'a mut self, arg: T) -> &'a mut Command {
-        self.args.push(arg.to_c_str());
+    pub fn arg<'a, T: BytesContainer>(&'a mut self, arg: T) -> &'a mut Command {
+        self.args.push(CString::from_slice(arg.container_as_bytes()));
         self
     }
 
     /// Add multiple arguments to pass to the program.
-    pub fn args<'a, T: ToCStr>(&'a mut self, args: &[T]) -> &'a mut Command {
-        self.args.extend(args.iter().map(|arg| arg.to_c_str()));;
+    pub fn args<'a, T: BytesContainer>(&'a mut self, args: &[T]) -> &'a mut Command {
+        self.args.extend(args.iter().map(|arg| {
+            CString::from_slice(arg.container_as_bytes())
+        }));
         self
     }
     // Get a mutable borrow of the environment variable map for this `Command`.
-    fn get_env_map<'a>(&'a mut self) -> &'a mut  EnvMap {
+    fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap {
         match self.env {
             Some(ref mut map) => map,
             None => {
                 // if the env is currently just inheriting from the parent's,
                 // materialize the parent's env into a hashtable.
-                self.env = Some(os::env_as_bytes().into_iter()
-                                   .map(|(k, v)| (EnvKey(k.to_c_str()),
-                                                  v.to_c_str()))
-                                   .collect());
+                self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| {
+                    (EnvKey(CString::from_slice(k.as_slice())),
+                     CString::from_slice(v.as_slice()))
+                }).collect());
                 self.env.as_mut().unwrap()
             }
         }
@@ -249,15 +252,20 @@ fn get_env_map<'a>(&'a mut self) -> &'a mut  EnvMap {
     ///
     /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
     /// and case-sensitive on all other platforms.
-    pub fn env<'a, T: ToCStr, U: ToCStr>(&'a mut self, key: T, val: U)
-                                         -> &'a mut Command {
-        self.get_env_map().insert(EnvKey(key.to_c_str()), val.to_c_str());
+    pub fn env<'a, T, U>(&'a mut self, key: T, val: U)
+                         -> &'a mut Command
+                         where T: BytesContainer, U: BytesContainer {
+        let key = EnvKey(CString::from_slice(key.container_as_bytes()));
+        let val = CString::from_slice(val.container_as_bytes());
+        self.get_env_map().insert(key, val);
         self
     }
 
     /// Removes an environment variable mapping.
-    pub fn env_remove<'a, T: ToCStr>(&'a mut self, key: T) -> &'a mut Command {
-        self.get_env_map().remove(&EnvKey(key.to_c_str()));
+    pub fn env_remove<'a, T>(&'a mut self, key: T) -> &'a mut Command
+                             where T: BytesContainer {
+        let key = EnvKey(CString::from_slice(key.container_as_bytes()));
+        self.get_env_map().remove(&key);
         self
     }
 
@@ -265,16 +273,19 @@ pub fn env_remove<'a, T: ToCStr>(&'a mut self, key: T) -> &'a mut Command {
     ///
     /// If the given slice contains multiple instances of an environment
     /// variable, the *rightmost* instance will determine the value.
-    pub fn env_set_all<'a, T: ToCStr, U: ToCStr>(&'a mut self, env: &[(T,U)])
-                                                 -> &'a mut Command {
-        self.env = Some(env.iter().map(|&(ref k, ref v)| (EnvKey(k.to_c_str()), v.to_c_str()))
-                                  .collect());
+    pub fn env_set_all<'a, T, U>(&'a mut self, env: &[(T,U)])
+                                 -> &'a mut Command
+                                 where T: BytesContainer, U: BytesContainer {
+        self.env = Some(env.iter().map(|&(ref k, ref v)| {
+            (EnvKey(CString::from_slice(k.container_as_bytes())),
+             CString::from_slice(v.container_as_bytes()))
+        }).collect());
         self
     }
 
     /// Set the working directory for the child process.
     pub fn cwd<'a>(&'a mut self, dir: &Path) -> &'a mut Command {
-        self.cwd = Some(dir.to_c_str());
+        self.cwd = Some(CString::from_slice(dir.as_vec()));
         self
     }
 
@@ -389,9 +400,9 @@ impl fmt::Show for Command {
     /// non-utf8 data is lossily converted using the utf8 replacement
     /// character.
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes_no_nul())));
+        try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes())));
         for arg in self.args.iter() {
-            try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes_no_nul())));
+            try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes())));
         }
         Ok(())
     }
@@ -1208,13 +1219,13 @@ fn dont_close_fd_on_command_spawn() {
     #[test]
     #[cfg(windows)]
     fn env_map_keys_ci() {
-        use c_str::ToCStr;
+        use ffi::CString;
         use super::EnvKey;
         let mut cmd = Command::new("");
         cmd.env("path", "foo");
         cmd.env("Path", "bar");
         let env = &cmd.env.unwrap();
-        let val = env.get(&EnvKey("PATH".to_c_str()));
-        assert!(val.unwrap() == &"bar".to_c_str());
+        let val = env.get(&EnvKey(CString::from_slice(b"PATH")));
+        assert!(val.unwrap() == &CString::from_slice(b"bar"));
     }
 }
index 608ad9882b97719fe487fdcd08b510d49fb82c73..2d3a4639379cfe36276b2e6505c1f611fe4e2d09 100644 (file)
 
 /* Runtime and platform support */
 
-pub mod thread_local;
-pub mod c_str;
-pub mod c_vec;
+pub mod thread_local; // first for macros
+
 pub mod dynamic_lib;
+pub mod ffi;
 pub mod fmt;
 pub mod io;
 pub mod os;
index be8f82349c2224496729c0adb2060dc888ff5a35..300ceec4b45bf3a047a54a0947a29395cd8accc3 100644 (file)
 use sync::atomic::{AtomicInt, ATOMIC_INT_INIT, Ordering};
 use vec::Vec;
 
-#[cfg(unix)] use c_str::ToCStr;
+#[cfg(unix)] use ffi::{self, CString};
 
-#[cfg(unix)]
-pub use sys::ext as unix;
-#[cfg(windows)]
-pub use sys::ext as windows;
+#[cfg(unix)] pub use sys::ext as unix;
+#[cfg(windows)] pub use sys::ext as windows;
 
 /// Get the number of cores available
 pub fn num_cpus() -> uint {
@@ -196,15 +194,14 @@ pub fn getenv(n: &str) -> Option<String> {
 ///
 /// Panics if `n` has any interior NULs.
 pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
-    use c_str::CString;
-
     unsafe {
         with_env_lock(|| {
-            let s = n.with_c_str(|buf| libc::getenv(buf));
+            let s = CString::from_slice(n.as_bytes());
+            let s = libc::getenv(s.as_ptr()) as *const _;
             if s.is_null() {
                 None
             } else {
-                Some(CString::new(s as *const libc::c_char, false).as_bytes_no_nul().to_vec())
+                Some(ffi::c_str_to_bytes(&s).to_vec())
             }
         })
     }
@@ -253,13 +250,12 @@ pub fn setenv<T: BytesContainer>(n: &str, v: T) {
     fn _setenv(n: &str, v: &[u8]) {
         unsafe {
             with_env_lock(|| {
-                n.with_c_str(|nbuf| {
-                    v.with_c_str(|vbuf| {
-                        if libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1) != 0 {
-                            panic!(IoError::last_error());
-                        }
-                    })
-                })
+                let k = CString::from_slice(n.as_bytes());
+                let v = CString::from_slice(v);
+                if libc::funcs::posix01::unistd::setenv(k.as_ptr(),
+                                                        v.as_ptr(), 1) != 0 {
+                    panic!(IoError::last_error());
+                }
             })
         }
     }
@@ -289,11 +285,10 @@ pub fn unsetenv(n: &str) {
     fn _unsetenv(n: &str) {
         unsafe {
             with_env_lock(|| {
-                n.with_c_str(|nbuf| {
-                    if libc::funcs::posix01::unistd::unsetenv(nbuf) != 0 {
-                        panic!(IoError::last_error());
-                    }
-                })
+                let nbuf = CString::from_slice(n.as_bytes());
+                if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
+                    panic!(IoError::last_error());
+                }
             })
         }
     }
@@ -618,11 +613,10 @@ pub fn get_exit_status() -> int {
 #[cfg(target_os = "macos")]
 unsafe fn load_argc_and_argv(argc: int,
                              argv: *const *const c_char) -> Vec<Vec<u8>> {
-    use c_str::CString;
     use iter::range;
 
     range(0, argc as uint).map(|i| {
-        CString::new(*argv.offset(i as int), false).as_bytes_no_nul().to_vec()
+        ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec()
     }).collect()
 }
 
@@ -652,7 +646,6 @@ fn real_args_as_bytes() -> Vec<Vec<u8>> {
 // res
 #[cfg(target_os = "ios")]
 fn real_args_as_bytes() -> Vec<Vec<u8>> {
-    use c_str::CString;
     use iter::range;
     use mem;
 
index bf9ffbffe7d508b1f26bd331875b71493222943c..2f014872402cf2d794d145342130e58eb9a072d0 100644 (file)
@@ -62,7 +62,7 @@
 #![experimental]
 
 use core::kinds::Sized;
-use c_str::CString;
+use ffi::CString;
 use clone::Clone;
 use fmt;
 use iter::IteratorExt;
@@ -892,7 +892,7 @@ fn container_as_bytes(&self) -> &[u8] {
 impl BytesContainer for CString {
     #[inline]
     fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
-        self.as_bytes_no_nul()
+        self.as_bytes()
     }
 }
 
@@ -913,21 +913,3 @@ fn is_str(_: Option<& &'a T>) -> bool { BytesContainer::is_str(None::<&T>) }
 fn contains_nul<T: BytesContainer>(v: &T) -> bool {
     v.container_as_bytes().iter().any(|&x| x == 0)
 }
-
-#[cfg(test)]
-mod tests {
-    use prelude::v1::*;
-    use c_str::ToCStr;
-    use path::{WindowsPath, PosixPath};
-
-    #[test]
-    fn test_cstring() {
-        let input = "/foo/bar/baz";
-        let path: PosixPath = PosixPath::new(input.to_c_str());
-        assert_eq!(path.as_vec(), input.as_bytes());
-
-        let input = r"\foo\bar\baz";
-        let path: WindowsPath = WindowsPath::new(input.to_c_str());
-        assert_eq!(path.as_str().unwrap(), input);
-    }
-}
index ae82e201cb8555793b4f33efd2366c98fecfad5e..013212b27058c3d0168175de08643680141b46c7 100644 (file)
 
 //! POSIX file path handling
 
-use c_str::{CString, ToCStr};
 use clone::Clone;
-use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
 use hash;
 use io::Writer;
 use iter::{AdditiveIterator, Extend};
 use iter::{Iterator, IteratorExt, Map};
-use option::Option;
-use option::Option::{None, Some};
 use kinds::Sized;
-use str::{FromStr, Str};
-use str;
-use slice::{Split, AsSlice, SliceConcatExt, SliceExt};
+use option::Option::{self, Some, None};
+use slice::{AsSlice, Split, SliceExt, SliceConcatExt};
+use str::{self, FromStr, StrExt};
 use vec::Vec;
 
 use super::{BytesContainer, GenericPath, GenericPathUnsafe};
@@ -86,26 +83,6 @@ fn from_str(s: &str) -> Option<Path> {
     }
 }
 
-// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
-// additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
-// reference.
-
-impl ToCStr for Path {
-    #[inline]
-    fn to_c_str(&self) -> CString {
-        // The Path impl guarantees no internal NUL
-        unsafe { self.to_c_str_unchecked() }
-    }
-
-    #[inline]
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        self.as_vec().to_c_str_unchecked()
-    }
-}
-
 impl<S: hash::Writer> hash::Hash<S> for Path {
     #[inline]
     fn hash(&self, state: &mut S) {
index cf8bc0e6242b312752e0ac621563ead9f994d2a5..05129a7ab9da3988c352337e8980c836caec8521 100644 (file)
 use self::PathPrefix::*;
 
 use ascii::AsciiExt;
-use c_str::{CString, ToCStr};
 use char::CharExt;
 use clone::Clone;
-use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
 use hash;
 use io::Writer;
 use iter::{AdditiveIterator, Extend};
 use iter::{Iterator, IteratorExt, Map, repeat};
 use mem;
-use option::Option;
-use option::Option::{Some, None};
+use option::Option::{self, Some, None};
 use slice::{SliceExt, SliceConcatExt};
 use str::{SplitTerminator, FromStr, StrExt};
 use string::{String, ToString};
@@ -112,26 +110,6 @@ fn from_str(s: &str) -> Option<Path> {
     }
 }
 
-// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
-// additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
-// reference.
-
-impl ToCStr for Path {
-    #[inline]
-    fn to_c_str(&self) -> CString {
-        // The Path impl guarantees no internal NUL
-        unsafe { self.to_c_str_unchecked() }
-    }
-
-    #[inline]
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        self.as_vec().to_c_str_unchecked()
-    }
-}
-
 impl<S: hash::Writer> hash::Hash<S> for Path {
     #[cfg(not(test))]
     #[inline]
index 4734a39c8354257a6fa21ed236160c8f42b964e5..86abacb936501f63124755cd6baeef981c9c7474 100644 (file)
@@ -46,8 +46,9 @@ pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
 mod imp {
     use prelude::v1::*;
 
+    use libc;
     use mem;
-    use slice;
+    use ffi;
 
     use sync::{StaticMutex, MUTEX_INIT};
 
@@ -95,13 +96,9 @@ fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
     }
 
     unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> {
+        let argv = argv as *const *const libc::c_char;
         range(0, argc as uint).map(|i| {
-            let arg = *argv.offset(i as int);
-            let mut len = 0u;
-            while *arg.offset(len as int) != 0 {
-                len += 1u;
-            }
-            slice::from_raw_buf(&arg, len).to_vec()
+            ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec()
         }).collect()
     }
 
index 578239c9cc42ee7237980ca00a840d6888e28414..bb0b6fe804bea4e676c0520cee80d4539c8b95e6 100644 (file)
@@ -15,7 +15,7 @@
 use prelude::v1::*;
 
 use os;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
 
 pub use sys::backtrace::write;
 
index a48a8edd82f60224e86a8cb53e14976c1ca069ae..71169386c186aee9400b363232787cf25c4a64af 100644 (file)
@@ -67,7 +67,7 @@
 use intrinsics;
 use libc::c_void;
 use mem;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
 use sync::{Once, ONCE_INIT};
 
 use rt::libunwind as uw;
index 883a01fa31801bebb237d1c6de79b64a6c32ff13..bc01ce926f8bc4306c43732cfdc51f8a546506af 100644 (file)
@@ -19,7 +19,7 @@
 use os;
 use slice;
 use str;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
 
 /// Dynamically inquire about whether we're running under V.
 /// You should usually not use this unless your test definitely
index a441e55a732b01049a187df94b611ce36e8edafe..a31dcc9884f465fa74c4311f443ac670853c0dac 100644 (file)
@@ -14,7 +14,7 @@
 use io::{self, IoError, IoResult};
 use prelude::v1::*;
 use sys::{last_error, retry};
-use c_str::CString;
+use ffi::CString;
 use num::Int;
 use path::BytesContainer;
 use collections;
index 3f67b284f688794d2611944e327463d0fce373c3..4cf891ac4985eba360859a1cff038719ce3ca9a8 100644 (file)
 use self::SocketStatus::*;
 use self::InAddr::*;
 
-use c_str::ToCStr;
+use ffi::CString;
+use ffi;
 use io::net::addrinfo;
 use io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
 use io::{IoResult, IoError};
 use libc::{self, c_char, c_int};
-use c_str::CString;
 use mem;
 use num::Int;
 use ptr::{self, null, null_mut};
+use str;
 use sys::{self, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
           wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
           decode_error_detailed};
@@ -234,9 +235,9 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>,
 
     assert!(host.is_some() || servname.is_some());
 
-    let c_host = host.map(|x| x.to_c_str());
+    let c_host = host.map(|x| CString::from_slice(x.as_bytes()));
     let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
-    let c_serv = servname.map(|x| x.to_c_str());
+    let c_serv = servname.map(|x| CString::from_slice(x.as_bytes()));
     let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
 
     let hint = hint.map(|hint| {
@@ -324,7 +325,8 @@ pub fn get_address_name(addr: IpAddr) -> Result<String, IoError> {
     }
 
     unsafe {
-        Ok(CString::new(hostbuf.as_ptr(), false).as_str().unwrap().to_string())
+        Ok(str::from_utf8(ffi::c_str_to_bytes(&hostbuf.as_ptr()))
+               .unwrap().to_string())
     }
 }
 
index 5b261ea6b9e58a85e9c5a94bc6da6ae4304ff890..ca268a8f27ff34680a915eff95255b7f4acd2093 100644 (file)
 /// to symbols. This is a bit of a hokey implementation as-is, but it works for
 /// all unix platforms we support right now, so it at least gets the job done.
 
-use c_str::CString;
-use io::{IoResult, Writer};
+use prelude::v1::*;
+
+use ffi;
+use io::IoResult;
 use libc;
 use mem;
-use option::Option::{self, Some, None};
-use result::Result::{Ok, Err};
+use str;
 use sync::{StaticMutex, MUTEX_INIT};
 
 use sys_common::backtrace::*;
 #[cfg(all(target_os = "ios", target_arch = "arm"))]
 #[inline(never)]
 pub fn write(w: &mut Writer) -> IoResult<()> {
-    use iter::{IteratorExt, range};
     use result;
-    use slice::SliceExt;
 
     extern {
         fn backtrace(buf: *mut *mut libc::c_void,
@@ -234,19 +233,15 @@ fn dladdr(addr: *const libc::c_void,
         output(w, idx,addr, None)
     } else {
         output(w, idx, addr, Some(unsafe {
-            CString::new(info.dli_sname, false)
+            ffi::c_str_to_bytes(&info.dli_sname)
         }))
     }
 }
 
 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
 fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
-    use iter::{Iterator, IteratorExt};
     use os;
-    use path::GenericPath;
-    use ptr::PtrExt;
     use ptr;
-    use slice::SliceExt;
 
     ////////////////////////////////////////////////////////////////////////
     // libbacktrace.h API
@@ -368,15 +363,15 @@ unsafe fn init_state() -> *mut backtrace_state {
     if ret == 0 || data.is_null() {
         output(w, idx, addr, None)
     } else {
-        output(w, idx, addr, Some(unsafe { CString::new(data, false) }))
+        output(w, idx, addr, Some(unsafe { ffi::c_str_to_bytes(&data) }))
     }
 }
 
 // Finally, after all that work above, we can emit a symbol.
 fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void,
-          s: Option<CString>) -> IoResult<()> {
+          s: Option<&[u8]>) -> IoResult<()> {
     try!(write!(w, "  {:2}: {:2$} - ", idx, addr, HEX_WIDTH));
-    match s.as_ref().and_then(|c| c.as_str()) {
+    match s.and_then(|s| str::from_utf8(s).ok()) {
         Some(string) => try!(demangle(w, string)),
         None => try!(write!(w, "<unknown>")),
     }
index b49ace8e2f8d83509a13525f0744f7d206d1d28d..1ad775517bba714aac62f8ea639ed31660d1d935 100644 (file)
@@ -12,7 +12,7 @@
 
 use prelude::v1::*;
 
-use c_str::{CString, ToCStr};
+use ffi::{self, CString};
 use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
 use io::{IoResult, FileStat, SeekStyle};
 use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
@@ -150,6 +150,10 @@ fn drop(&mut self) {
     }
 }
 
+fn cstr(path: &Path) -> CString {
+    CString::from_slice(path.as_vec())
+}
+
 pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
     let flags = match fm {
         Open => 0,
@@ -165,7 +169,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
                             libc::S_IRUSR | libc::S_IWUSR),
     };
 
-    let path = path.to_c_str();
+    let path = cstr(path);
     match retry(|| unsafe { libc::open(path.as_ptr(), flags, mode) }) {
         -1 => Err(super::last_error()),
         fd => Ok(FileDesc::new(fd, true)),
@@ -173,7 +177,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
 }
 
 pub fn mkdir(p: &Path, mode: uint) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     mkerr_libc(unsafe { libc::mkdir(p.as_ptr(), mode as libc::mode_t) })
 }
 
@@ -182,7 +186,6 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
     use libc::{opendir, readdir_r, closedir};
 
     fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
-        let root = unsafe { CString::new(root.as_ptr(), false) };
         let root = Path::new(root);
 
         dirs.into_iter().filter(|path| {
@@ -199,7 +202,7 @@ fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
     let mut buf = Vec::<u8>::with_capacity(size as uint);
     let ptr = buf.as_mut_ptr() as *mut dirent_t;
 
-    let p = p.to_c_str();
+    let p = CString::from_slice(p.as_vec());
     let dir_ptr = unsafe {opendir(p.as_ptr())};
 
     if dir_ptr as uint != 0 {
@@ -207,10 +210,9 @@ fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
         let mut entry_ptr = 0 as *mut dirent_t;
         while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
             if entry_ptr.is_null() { break }
-            let cstr = unsafe {
-                CString::new(rust_list_dir_val(entry_ptr), false)
-            };
-            paths.push(Path::new(cstr));
+            paths.push(unsafe {
+                Path::new(ffi::c_str_to_bytes(&rust_list_dir_val(entry_ptr)))
+            });
         }
         assert_eq!(unsafe { closedir(dir_ptr) }, 0);
         Ok(prune(&p, paths))
@@ -220,39 +222,39 @@ fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
 }
 
 pub fn unlink(p: &Path) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     mkerr_libc(unsafe { libc::unlink(p.as_ptr()) })
 }
 
 pub fn rename(old: &Path, new: &Path) -> IoResult<()> {
-    let old = old.to_c_str();
-    let new = new.to_c_str();
+    let old = cstr(old);
+    let new = cstr(new);
     mkerr_libc(unsafe {
         libc::rename(old.as_ptr(), new.as_ptr())
     })
 }
 
 pub fn chmod(p: &Path, mode: uint) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     mkerr_libc(retry(|| unsafe {
         libc::chmod(p.as_ptr(), mode as libc::mode_t)
     }))
 }
 
 pub fn rmdir(p: &Path) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) })
 }
 
 pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     mkerr_libc(retry(|| unsafe {
         libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
     }))
 }
 
 pub fn readlink(p: &Path) -> IoResult<Path> {
-    let c_path = p.to_c_str();
+    let c_path = cstr(p);
     let p = c_path.as_ptr();
     let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
     if len == -1 {
@@ -273,14 +275,14 @@ pub fn readlink(p: &Path) -> IoResult<Path> {
 }
 
 pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
-    let src = src.to_c_str();
-    let dst = dst.to_c_str();
+    let src = cstr(src);
+    let dst = cstr(dst);
     mkerr_libc(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })
 }
 
 pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
-    let src = src.to_c_str();
-    let dst = dst.to_c_str();
+    let src = cstr(src);
+    let dst = cstr(dst);
     mkerr_libc(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })
 }
 
@@ -328,7 +330,7 @@ fn gen(_stat: &libc::stat) -> u64 { 0 }
 }
 
 pub fn stat(p: &Path) -> IoResult<FileStat> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     let mut stat: libc::stat = unsafe { mem::zeroed() };
     match unsafe { libc::stat(p.as_ptr(), &mut stat) } {
         0 => Ok(mkstat(&stat)),
@@ -337,7 +339,7 @@ pub fn stat(p: &Path) -> IoResult<FileStat> {
 }
 
 pub fn lstat(p: &Path) -> IoResult<FileStat> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     let mut stat: libc::stat = unsafe { mem::zeroed() };
     match unsafe { libc::lstat(p.as_ptr(), &mut stat) } {
         0 => Ok(mkstat(&stat)),
@@ -346,7 +348,7 @@ pub fn lstat(p: &Path) -> IoResult<FileStat> {
 }
 
 pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     let buf = libc::utimbuf {
         actime: (atime / 1000) as libc::time_t,
         modtime: (mtime / 1000) as libc::time_t,
index ea0d230e8b210c751d80df67a093e7f25f146dd5..6a408aa60f0bfb2aa8bbcbbf8fe3a691fb681e0e 100644 (file)
 #![allow(unused_unsafe)]
 #![allow(unused_mut)]
 
-extern crate libc;
-
-use num;
-use num::{Int, SignedInt};
 use prelude::v1::*;
+
+use ffi;
 use io::{self, IoResult, IoError};
+use libc;
+use num::{Int, SignedInt};
+use num;
+use str;
 use sys_common::mkerr_libc;
 
 macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
@@ -78,11 +80,10 @@ pub fn last_net_error() -> IoError {
 }
 
 pub fn last_gai_error(s: libc::c_int) -> IoError {
-    use c_str::CString;
 
     let mut err = decode_error(s);
     err.detail = Some(unsafe {
-        CString::new(gai_strerror(s), false).as_str().unwrap().to_string()
+        str::from_utf8(ffi::c_str_to_bytes(&gai_strerror(s))).unwrap().to_string()
     });
     err
 }
index 181b8fdd0f8a11af8e610cd751b1aebc6d72da48..175c4e2e353f91044fa0453395c27f173671a870 100644 (file)
 
 use prelude::v1::*;
 
-use c_str::ToCStr;
 use error::{FromError, Error};
+use ffi::{self, CString};
 use fmt;
 use io::{IoError, IoResult};
 use libc::{self, c_int, c_char, c_void};
+use os::TMPBUF_SZ;
 use os;
 use path::{BytesContainer};
 use ptr;
+use str;
 use sys::fs::FileDesc;
 
-use os::TMPBUF_SZ;
-
 const BUF_BYTES : uint = 2048u;
 
 /// Returns the platform-specific value of errno
@@ -108,7 +108,8 @@ fn __xpg_strerror_r(errnum: c_int,
             panic!("strerror_r failure");
         }
 
-        String::from_raw_buf(p as *const u8)
+        let p = p as *const _;
+        str::from_utf8(ffi::c_str_to_bytes(&p)).unwrap().to_string()
     }
 }
 
@@ -122,21 +123,17 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
 }
 
 pub fn getcwd() -> IoResult<Path> {
-    use c_str::CString;
-
     let mut buf = [0 as c_char; BUF_BYTES];
     unsafe {
         if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
             Err(IoError::last_error())
         } else {
-            Ok(Path::new(CString::new(buf.as_ptr(), false)))
+            Ok(Path::new(ffi::c_str_to_bytes(&buf.as_ptr())))
         }
     }
 }
 
 pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
-    use c_str::CString;
-
     extern {
         fn rust_env_pairs() -> *const *const c_char;
     }
@@ -147,8 +144,7 @@ pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
     }
     let mut result = Vec::new();
     while *environ != 0 as *const _ {
-        let env_pair =
-            CString::new(*environ, false).as_bytes_no_nul().to_vec();
+        let env_pair = ffi::c_str_to_bytes(&*environ).to_vec();
         result.push(env_pair);
         environ = environ.offset(1);
     }
@@ -234,14 +230,13 @@ pub fn load_self() -> Option<Vec<u8>> {
 }
 
 pub fn chdir(p: &Path) -> IoResult<()> {
-    p.with_c_str(|buf| {
-        unsafe {
-            match libc::chdir(buf) == (0 as c_int) {
-                true => Ok(()),
-                false => Err(IoError::last_error()),
-            }
+    let p = CString::from_slice(p.as_vec());
+    unsafe {
+        match libc::chdir(p.as_ptr()) == (0 as c_int) {
+            true => Ok(()),
+            false => Err(IoError::last_error()),
         }
-    })
+    }
 }
 
 pub fn page_size() -> uint {
index 9063fbc2ba955b9466f3b12b9b9164f8a9397b36..158a1ce220411439bfeb2f188fdb002bf12ed14d 100644 (file)
@@ -10,8 +10,8 @@
 
 use prelude::v1::*;
 
+use ffi::CString;
 use libc;
-use c_str::CString;
 use mem;
 use sync::{Arc, Mutex};
 use sync::atomic::{AtomicBool, Ordering};
@@ -48,7 +48,7 @@ fn addr_to_sockaddr_un(addr: &CString,
     }
     s.sun_family = libc::AF_UNIX as libc::sa_family_t;
     for (slot, value) in s.sun_path.iter_mut().zip(addr.iter()) {
-        *slot = value;
+        *slot = *value;
     }
 
     // count the null terminator
index b73919fe2a2cc5b063b65624bea6c1a467b734dd..5bc6b0c703b1c9c90057820cb37f2880bec164aa 100644 (file)
@@ -11,8 +11,8 @@
 use prelude::v1::*;
 use self::Req::*;
 
-use c_str::{CString, ToCStr};
 use collections;
+use ffi::CString;
 use hash::Hash;
 use io::process::{ProcessExit, ExitStatus, ExitSignal};
 use io::{self, IoResult, IoError, EndOfFile};
@@ -101,7 +101,7 @@ unsafe fn set_cloexec(fd: c_int) {
 
                 // We may use this in the child, so perform allocations before the
                 // fork
-                let devnull = "/dev/null".to_c_str();
+                let devnull = b"/dev/null\0";
 
                 set_cloexec(output.fd());
 
@@ -204,7 +204,7 @@ fn fail(output: &mut FileDesc) -> ! {
                             } else {
                                 libc::O_RDWR
                             };
-                            libc::open(devnull.as_ptr(), flags, 0)
+                            libc::open(devnull.as_ptr() as *const _, flags, 0)
                         }
                         Some(obj) => {
                             let fd = obj.as_inner().fd();
index 11f29232a925d0e3625a607a9ee1d7c978e5f5db..62f3242a2062580360ee277bc83ce9be8cf97767 100644 (file)
@@ -54,7 +54,7 @@
 use mem;
 use os;
 use ptr;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
 use sync::mpsc::{channel, Sender, Receiver, TryRecvError};
 use sys::c;
 use sys::fs::FileDesc;
index 319a458087b9b51f949c997cf08c101ca55b662f..4ccecfd1f5f2e6cc35f754cbe7049dcd23181388 100644 (file)
@@ -21,7 +21,8 @@
 /// copy of that function in my mingw install (maybe it was broken?). Instead,
 /// this takes the route of using StackWalk64 in order to walk the stack.
 
-use c_str::CString;
+use dynamic_lib::DynamicLibrary;
+use ffi;
 use intrinsics;
 use io::{IoResult, Writer};
 use libc;
 use option::Option::{Some, None};
 use path::Path;
 use result::Result::{Ok, Err};
-use sync::{StaticMutex, MUTEX_INIT};
 use slice::SliceExt;
-use str::StrExt;
-use dynamic_lib::DynamicLibrary;
+use str::{self, StrExt};
+use sync::{StaticMutex, MUTEX_INIT};
 
 use sys_common::backtrace::*;
 
@@ -357,11 +357,11 @@ macro_rules! sym{ ($e:expr, $t:ident) => (unsafe {
 
         if ret == libc::TRUE {
             try!(write!(w, " - "));
-            let cstr = unsafe { CString::new(info.Name.as_ptr(), false) };
-            let bytes = cstr.as_bytes();
-            match cstr.as_str() {
-                Some(s) => try!(demangle(w, s)),
-                None => try!(w.write(bytes[..bytes.len()-1])),
+            let ptr = info.Name.as_ptr() as *const libc::c_char;
+            let bytes = unsafe { ffi::c_str_to_bytes(&ptr) };
+            match str::from_utf8(bytes) {
+                Ok(s) => try!(demangle(w, s)),
+                Err(..) => try!(w.write(bytes[..bytes.len()-1])),
             }
         }
         try!(w.write(&['\n' as u8]));
index 1ee57434fb91ada83e4cad503654a6d7b9332afd..945c2e8e7d156ce501ca029f5b54483123a3acd5 100644 (file)
@@ -133,7 +133,7 @@ pub mod compat {
     use intrinsics::{atomic_store_relaxed, transmute};
     use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
     use prelude::v1::*;
-    use c_str::ToCStr;
+    use ffi::CString;
 
     extern "system" {
         fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
@@ -147,14 +147,13 @@ pub mod compat {
     unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) {
         let mut module: Vec<u16> = module.utf16_units().collect();
         module.push(0);
-        symbol.with_c_str(|symbol| {
-            let handle = GetModuleHandleW(module.as_ptr());
-            let func: uint = transmute(GetProcAddress(handle, symbol));
-            atomic_store_relaxed(ptr, if func == 0 {
-                fallback
-            } else {
-                func
-            })
+        let symbol = CString::from_slice(symbol.as_bytes());
+        let handle = GetModuleHandleW(module.as_ptr());
+        let func: uint = transmute(GetProcAddress(handle, symbol.as_ptr()));
+        atomic_store_relaxed(ptr, if func == 0 {
+            fallback
+        } else {
+            func
         })
     }
 
index 9a9423006568020e2d83e73fae538d8fd4c944b7..f8c75335b35dc31059790965e7c89e54f52322ec 100644 (file)
@@ -13,7 +13,6 @@
 use alloc::arc::Arc;
 use libc::{self, c_int};
 
-use c_str::CString;
 use mem;
 use sys::os::fill_utf16_buf_and_decode;
 use path;
index 9057515cad294c51f849a0fff470004e77745c97..9996909f2f5bbc18a9781018bd4dd4aaaf952fd1 100644 (file)
 use prelude::v1::*;
 
 use libc;
-use c_str::CString;
+use ffi::CString;
+use io::{self, IoError, IoResult};
 use mem;
 use ptr;
-use sync::{Arc, Mutex};
+use str;
 use sync::atomic::{AtomicBool, Ordering};
-use io::{self, IoError, IoResult};
+use sync::{Arc, Mutex};
 
 use sys_common::{self, eof};
 
-use super::{c, os, timer, to_utf16, decode_error_detailed};
+use super::{c, os, timer, decode_error_detailed};
+
+fn to_utf16(c: &CString) -> IoResult<Vec<u16>> {
+    super::to_utf16(str::from_utf8(c.as_bytes()).ok())
+}
 
 struct Event(libc::HANDLE);
 
@@ -270,7 +275,7 @@ fn try_connect(p: *const u16) -> Option<libc::HANDLE> {
     }
 
     pub fn connect(addr: &CString, timeout: Option<u64>) -> IoResult<UnixStream> {
-        let addr = try!(to_utf16(addr.as_str()));
+        let addr = try!(to_utf16(addr));
         let start = timer::now();
         loop {
             match UnixStream::try_connect(addr.as_ptr()) {
@@ -571,7 +576,7 @@ pub fn bind(addr: &CString) -> IoResult<UnixListener> {
         // Although we technically don't need the pipe until much later, we
         // create the initial handle up front to test the validity of the name
         // and such.
-        let addr_v = try!(to_utf16(addr.as_str()));
+        let addr_v = try!(to_utf16(addr));
         let ret = unsafe { pipe(addr_v.as_ptr(), true) };
         if ret == libc::INVALID_HANDLE_VALUE {
             Err(super::last_error())
@@ -661,7 +666,7 @@ pub fn accept(&mut self) -> IoResult<UnixStream> {
         // proceed in accepting new clients in the future
         if self.inner.closed.load(Ordering::SeqCst) { return Err(eof()) }
 
-        let name = try!(to_utf16(self.listener.name.as_str()));
+        let name = try!(to_utf16(&self.listener.name));
 
         // Once we've got a "server handle", we need to wait for a client to
         // connect. The ConnectNamedPipe function will block this thread until
@@ -753,7 +758,7 @@ pub fn handle(&self) -> libc::HANDLE {
 
 impl Clone for UnixAcceptor {
     fn clone(&self) -> UnixAcceptor {
-        let name = to_utf16(self.listener.name.as_str()).ok().unwrap();
+        let name = to_utf16(&self.listener.name).ok().unwrap();
         UnixAcceptor {
             inner: self.inner.clone(),
             event: Event::new(true, false).ok().unwrap(),
index 81e8f974a12238abf9fad4e13d79571078cc050f..9b3f2ca03736efa06114e2177623ab3030838ec4 100644 (file)
 
 use prelude::v1::*;
 
+use collections;
+use ffi::CString;
+use hash::Hash;
+use io::fs::PathExtensions;
+use io::process::{ProcessExit, ExitStatus, ExitSignal};
+use io::{IoResult, IoError};
+use io;
 use libc::{pid_t, c_void, c_int};
 use libc;
-use c_str::{CString, ToCStr};
-use io;
 use mem;
 use os;
-use ptr;
-use io::process::{ProcessExit, ExitStatus, ExitSignal};
-use collections;
 use path::BytesContainer;
-use hash::Hash;
-use io::{IoResult, IoError};
-
+use ptr;
+use str;
+use sys::fs::FileDesc;
 use sys::fs;
 use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
-use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
 use sys_common::{AsInner, mkerr_libc, timeout};
 
-use io::fs::PathExtensions;
-
 pub use sys_common::ProcessConfig;
 
 /// A value representing a child process.
@@ -142,10 +141,10 @@ pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                 // Split the value and test each path to see if the
                 // program exists.
                 for path in os::split_paths(v.container_as_bytes()).into_iter() {
-                    let path = path.join(cfg.program().as_bytes_no_nul())
+                    let path = path.join(cfg.program().as_bytes())
                                    .with_extension(os::consts::EXE_EXTENSION);
                     if path.exists() {
-                        return Some(path.to_c_str())
+                        return Some(CString::from_slice(path.as_vec()))
                     }
                 }
                 break
@@ -363,11 +362,11 @@ fn zeroed_process_information() -> libc::types::os::arch::extra::PROCESS_INFORMA
 
 fn make_command_line(prog: &CString, args: &[CString]) -> String {
     let mut cmd = String::new();
-    append_arg(&mut cmd, prog.as_str()
+    append_arg(&mut cmd, str::from_utf8(prog.as_bytes()).ok()
                              .expect("expected program name to be utf-8 encoded"));
     for arg in args.iter() {
         cmd.push(' ');
-        append_arg(&mut cmd, arg.as_str()
+        append_arg(&mut cmd, str::from_utf8(arg.as_bytes()).ok()
                                 .expect("expected argument to be utf-8 encoded"));
     }
     return cmd;
@@ -449,7 +448,7 @@ fn with_dirp<T, F>(d: Option<&CString>, cb: F) -> T where
 {
     match d {
       Some(dir) => {
-          let dir_str = dir.as_str()
+          let dir_str = str::from_utf8(dir.as_bytes()).ok()
                            .expect("expected workingdirectory to be utf-8 encoded");
           let mut dir_str: Vec<u16> = dir_str.utf16_units().collect();
           dir_str.push(0);
index 0b4bea49fa2499d0481dbdcbe5178c20c8401fe9..6cd94ee5602aa5ccf3db96b0b1f3ccda3dcae6ef 100644 (file)
@@ -27,7 +27,7 @@ fn bar() { }
 fn baz() { }
 
 pub fn test() {
-    let none: Option<Path> = None; // appease the typechecker
+    let none: Option<&Path> = None; // appease the typechecker
     let lib = DynamicLibrary::open(none).unwrap();
     unsafe {
         assert!(lib.symbol::<int>("foo").is_ok());
index c95cf0bfdee453d8c5a43bd9c20ecab323c39fb6..22c322b86c97963d800c3485a482d2c7aa2d846d 100644 (file)
@@ -12,7 +12,7 @@
 
 extern crate libc;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 
 mod mlibc {
     use libc::{c_char, c_long, c_longlong};
@@ -24,11 +24,13 @@ mod mlibc {
 }
 
 fn atol(s: String) -> int {
-    s.as_slice().with_c_str(|x| unsafe { mlibc::atol(x) as int })
+    let c = CString::from_slice(s.as_bytes());
+    unsafe { mlibc::atol(c.as_ptr()) as int }
 }
 
 fn atoll(s: String) -> i64 {
-    s.as_slice().with_c_str(|x| unsafe { mlibc::atoll(x) as i64 })
+    let c = CString::from_slice(s.as_bytes());
+    unsafe { mlibc::atoll(c.as_ptr()) as i64 }
 }
 
 pub fn main() {
index 5e028d3774fc50d4c7c06edd1bc204e8a5600ae2..1a84236793b4f8d6d3d9f623b717fb227be4d9d9 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use std::{str, string};
-use std::c_str::ToCStr;
 
 const A: [u8; 2] = ['h' as u8, 'i' as u8];
 const B: &'static [u8; 2] = &A;
@@ -23,8 +22,5 @@ pub fn main() {
         assert_eq!(String::from_raw_buf_len(C, B.len()), "hi".to_string());
         assert!(*C == A[0]);
         assert!(*(&B[0] as *const u8) == A[0]);
-
-        let bar = str::from_utf8_unchecked(&A).to_c_str();
-        assert_eq!(bar.as_str(), "hi".to_c_str().as_str());
     }
 }
index 8a75fdd685dd1055fb2515d5372182a30cb50cee..dff1a1eaa0473aaf7b3a3225051da1d5072ad8ff 100644 (file)
@@ -11,7 +11,7 @@
 // ignore-fast doesn't like extern crate
 
 extern crate libc;
-use std::c_str::ToCStr;
+use std::ffi::CString;
 
 mod mlibc {
     use libc::{c_char, size_t};
@@ -24,11 +24,10 @@ mod mlibc {
 
 fn strlen(str: String) -> uint {
     // C string is terminated with a zero
-    str.as_slice().with_c_str(|buf| {
-        unsafe {
-            mlibc::my_strlen(buf) as uint
-        }
-    })
+    let s = CString::from_slice(str.as_bytes());
+    unsafe {
+        mlibc::my_strlen(s.as_ptr()) as uint
+    }
 }
 
 pub fn main() {
index c7aa405b513e465bb6404d80d57df928edb5e95b..d610bf09edb958b0503c7795b95f6011cd1a1b18 100644 (file)
@@ -13,8 +13,8 @@
 
 extern crate libc;
 
+use std::ffi::CString;
 use std::io::TempDir;
-use std::c_str::ToCStr;
 use std::io::fs::PathExtensions;
 use std::io::fs;
 use std::io;
@@ -31,20 +31,17 @@ fn rename_directory() {
         let test_file = &old_path.join("temp.txt");
 
         /* Write the temp input file */
-        let ostream = test_file.with_c_str(|fromp| {
-            "w+b".with_c_str(|modebuf| {
-                libc::fopen(fromp, modebuf)
-            })
-        });
+        let fromp = CString::from_slice(test_file.as_vec());
+        let modebuf = CString::from_slice(b"w+b");
+        let ostream = libc::fopen(fromp.as_ptr(), modebuf.as_ptr());
         assert!((ostream as uint != 0u));
         let s = "hello".to_string();
-        "hello".with_c_str(|buf| {
-            let write_len = libc::fwrite(buf as *const libc::c_void,
-                                         1u as libc::size_t,
-                                         (s.len() + 1u) as libc::size_t,
-                                         ostream);
-            assert_eq!(write_len, (s.len() + 1) as libc::size_t)
-        });
+        let buf = CString::from_slice(b"hello");
+        let write_len = libc::fwrite(buf.as_ptr() as *mut _,
+                                     1u as libc::size_t,
+                                     (s.len() + 1u) as libc::size_t,
+                                     ostream);
+        assert_eq!(write_len, (s.len() + 1) as libc::size_t);
         assert_eq!(libc::fclose(ostream), (0u as libc::c_int));
 
         let new_path = tmpdir.join_many(&["quux", "blat"]);
index ec320c1f8a3092b2407ab68cb1a595ed9d111018..de9d7880411a1426ae6c6d6d027f0004b21cac02 100644 (file)
@@ -10,7 +10,7 @@
 
 extern crate libc;
 
-use std::c_str::{CString, ToCStr};
+use std::ffi::{self, CString};
 use libc::{c_char, c_int};
 
 // ignore-fast doesn't like extern crate
 unsafe fn check<T>(expected: &str, f: |*mut c_char| -> T) {
     let mut x = [0 as c_char; 50];
     f(&mut x[0] as *mut c_char);
-    let res = CString::new(&x[0], false);
-    assert_eq!(expected, res.as_str().unwrap());
+    assert_eq!(expected.as_bytes(), ffi::c_str_to_bytes(&x.as_ptr()));
 }
 
 pub fn main() {
 
     unsafe {
         // Call with just the named parameter
-        "Hello World\n".with_c_str(|c| {
-            check("Hello World\n", |s| sprintf(s, c));
-        });
+        let c = CString::from_slice(b"Hello World\n");
+        check("Hello World\n", |s| sprintf(s, c.as_ptr()));
 
         // Call with variable number of arguments
-        "%d %f %c %s\n".with_c_str(|c| {
-            check("42 42.500000 a %d %f %c %s\n\n", |s| {
-                sprintf(s, c, 42i, 42.5f64, 'a' as c_int, c);
-            })
+        let c = CString::from_slice(b"%d %f %c %s\n");
+        check("42 42.500000 a %d %f %c %s\n\n", |s| {
+            sprintf(s, c.as_ptr(), 42i, 42.5f64, 'a' as c_int, c.as_ptr());
         });
 
         // Make a function pointer
-        let x: unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int = sprintf;
+        let x: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int = sprintf;
 
         // A function that takes a function pointer
-        unsafe fn call(p: unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int) {
-            // Call with just the named parameter via fn pointer
-            "Hello World\n".with_c_str(|c| {
-                check("Hello World\n", |s| p(s, c));
-            });
+        unsafe fn call(p: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) {
+            // Call with just the named parameter
+            let c = CString::from_slice(b"Hello World\n");
+            check("Hello World\n", |s| sprintf(s, c.as_ptr()));
 
             // Call with variable number of arguments
-            "%d %f %c %s\n".with_c_str(|c| {
-                check("42 42.500000 a %d %f %c %s\n\n", |s| {
-                    p(s, c, 42i, 42.5f64, 'a' as c_int, c);
-                })
+            let c = CString::from_slice(b"%d %f %c %s\n");
+            check("42 42.500000 a %d %f %c %s\n\n", |s| {
+                sprintf(s, c.as_ptr(), 42i, 42.5f64, 'a' as c_int, c.as_ptr());
             });
         }