1
Fork 0

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
This commit is contained in:
Alex Crichton 2014-11-25 13:28:35 -08:00
parent 1f732ef53d
commit ec7a50d20d
59 changed files with 1018 additions and 1998 deletions

View 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 @@ impl BytesContainer for Vec<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 @@ impl<'a, Sized? T: BytesContainer> BytesContainer for &'a 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);
}
}

View file

@ -10,19 +10,16 @@
//! 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 @@ impl FromStr for 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) {

View file

@ -15,17 +15,15 @@
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 @@ impl FromStr for 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]