about summary refs log tree commit diff
path: root/src/libstd/dynamic_lib.rs
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-11-25 13:28:35 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-01-05 08:00:13 -0800
commitec7a50d20dff416d9fec837a6492dfe244f5f3ab (patch)
tree559c2e05abb4f51d6309a1af3f4e1953a6627e3d /src/libstd/dynamic_lib.rs
parent1f732ef53d54ccfc3e7728390ffbcea8a696ecee (diff)
downloadrust-ec7a50d20dff416d9fec837a6492dfe244f5f3ab.tar.gz
rust-ec7a50d20dff416d9fec837a6492dfe244f5f3ab.zip
std: Redesign c_str and c_vec
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
Diffstat (limited to 'src/libstd/dynamic_lib.rs')
-rw-r--r--src/libstd/dynamic_lib.rs41
1 files changed, 18 insertions, 23 deletions
diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs
index de3d75ffb32..66cb1f2c948 100644
--- a/src/libstd/dynamic_lib.rs
+++ b/src/libstd/dynamic_lib.rs
@@ -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 @@ impl DynamicLibrary {
         // 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 @@ mod test {
           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 mod dl {
             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 @@ pub mod dl {
 
 #[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