Skip to content

Commit

Permalink
std: Stabilize the ffi module
Browse files Browse the repository at this point in the history
The two main sub-modules, `c_str` and `os_str`, have now had some time to bake
in the standard library. This commits performs a sweep over the modules adding
various stability tags.

The following APIs are now marked `#[stable]`

* `OsString`
* `OsStr`
* `OsString::from_string`
* `OsString::from_str`
* `OsString::new`
* `OsString::into_string`
* `OsString::push` (renamed from `push_os_str`, added an `AsOsStr` bound)
* various trait implementations for `OsString`
* `OsStr::from_str`
* `OsStr::to_str`
* `OsStr::to_string_lossy`
* `OsStr::to_os_string`
* various trait implementations for `OsStr`
* `CString`
* `CStr`
* `NulError`
* `CString::new` - this API's implementation may change as a result of
  rust-lang/rfcs#912 but the usage of `CString::new(thing)` looks like it is
  unlikely to change. Additionally, the `IntoBytes` bound is also likely to
  change but the set of implementors for the trait will not change (despite the
  trait perhaps being renamed).
* `CString::from_vec_unchecked`
* `CString::as_bytes`
* `CString::as_bytes_with_nul`
* `NulError::nul_position`
* `NulError::into_vec`
* `CStr::from_ptr`
* `CStr::as_ptr`
* `CStr::to_bytes`
* `CStr::to_bytes_with_nul`
* various trait implementations for `CStr`

The following APIs remain `#[unstable]`

* `OsStr*Ext` traits remain unstable as the organization of `os::platform` is
  uncertain still and the traits may change location.
* `AsOsStr` remains unstable as generic conversion traits are likely to be
  rethought soon.

The following APIs were deprecated

* `OsString::push_os_str` is now called `push` and takes `T: AsOsStr` instead (a
  superset of the previous functionality).
  • Loading branch information
alexcrichton committed Mar 5, 2015
1 parent 68740b4 commit 628f5d2
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 29 deletions.
1 change: 0 additions & 1 deletion src/compiletest/compiletest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#![feature(unicode)]
#![feature(core)]
#![feature(path)]
#![feature(os)]
#![feature(io)]
#![feature(fs)]
#![feature(net)]
Expand Down
9 changes: 4 additions & 5 deletions src/compiletest/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use procsrv;
use util::logv;

use std::env;
use std::ffi::OsStr;
use std::fmt;
use std::fs::{self, File};
use std::io::BufReader;
Expand Down Expand Up @@ -1323,7 +1322,7 @@ fn make_exe_name(config: &Config, testfile: &Path) -> PathBuf {
let mut f = output_base_name(config, testfile);
if !env::consts::EXE_SUFFIX.is_empty() {
let mut fname = f.file_name().unwrap().to_os_string();
fname.push_os_str(OsStr::from_str(env::consts::EXE_SUFFIX));
fname.push(env::consts::EXE_SUFFIX);
f.set_file_name(&fname);
}
f
Expand Down Expand Up @@ -1433,7 +1432,7 @@ fn make_out_name(config: &Config, testfile: &Path, extension: &str) -> PathBuf {
fn aux_output_dir_name(config: &Config, testfile: &Path) -> PathBuf {
let f = output_base_name(config, testfile);
let mut fname = f.file_name().unwrap().to_os_string();
fname.push_os_str(OsStr::from_str("libaux"));
fname.push("libaux");
f.with_file_name(&fname)
}

Expand Down Expand Up @@ -1647,8 +1646,8 @@ fn append_suffix_to_stem(p: &Path, suffix: &str) -> PathBuf {
p.to_path_buf()
} else {
let mut stem = p.file_stem().unwrap().to_os_string();
stem.push_os_str(OsStr::from_str("-"));
stem.push_os_str(OsStr::from_str(suffix));
stem.push("-");
stem.push(suffix);
p.with_file_name(&stem)
}
}
Expand Down
1 change: 0 additions & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
#![feature(unsafe_destructor)]
#![feature(staged_api)]
#![feature(std_misc)]
#![feature(os)]
#![feature(path)]
#![feature(fs)]
#![feature(io)]
Expand Down
1 change: 0 additions & 1 deletion src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#![feature(int_uint)]
#![feature(old_io)]
#![feature(libc)]
#![feature(os)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_trans/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use util::common::time;
use util::ppaux;
use util::sha2::{Digest, Sha256};

use std::ffi::{AsOsStr, OsString};
use std::ffi::OsString;
use std::fs::{self, TempDir, PathExt};
use std::io::{self, Read, Write};
use std::mem;
Expand Down Expand Up @@ -882,7 +882,7 @@ fn link_args(cmd: &mut Command,
let morestack = lib_path.join("libmorestack.a");

let mut v = OsString::from_str("-Wl,-force_load,");
v.push_os_str(morestack.as_os_str());
v.push(&morestack);
cmd.arg(&v);
} else {
cmd.args(&["-Wl,--whole-archive", "-lmorestack", "-Wl,--no-whole-archive"]);
Expand Down Expand Up @@ -1007,7 +1007,7 @@ fn link_args(cmd: &mut Command,

if sess.opts.cg.rpath {
let mut v = OsString::from_str("-Wl,-install_name,@rpath/");
v.push_os_str(out_filename.file_name().unwrap());
v.push(out_filename.file_name().unwrap());
cmd.arg(&v);
}
} else {
Expand Down Expand Up @@ -1107,7 +1107,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
&search_path[..],
&sess.diagnostic().handler);
let mut v = OsString::from_str("-Wl,-force_load,");
v.push_os_str(lib.as_os_str());
v.push(&lib);
cmd.arg(&v);
}
}
Expand Down
2 changes: 0 additions & 2 deletions src/librustc_trans/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,10 @@
#![feature(rustc_private)]
#![feature(unsafe_destructor)]
#![feature(staged_api)]
#![feature(std_misc)]
#![feature(unicode)]
#![feature(io)]
#![feature(fs)]
#![feature(path)]
#![feature(os)]
#![feature(tempdir)]

extern crate arena;
Expand Down
3 changes: 1 addition & 2 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::default::Default;
use std::ffi::OsStr;
use std::fmt;
use std::fs::{self, File};
use std::io::prelude::*;
Expand Down Expand Up @@ -770,7 +769,7 @@ impl<'a> SourceCollector<'a> {

let mut fname = p.file_name().expect("source has no filename")
.to_os_string();
fname.push_os_str(OsStr::from_str(".html"));
fname.push(".html");
cur.push(&fname);
let mut w = BufWriter::new(try!(File::create(&cur)));

Expand Down
28 changes: 28 additions & 0 deletions src/libstd/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "std_misc")]

use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use error::{Error, FromError};
use fmt;
Expand Down Expand Up @@ -59,6 +61,7 @@ use vec::Vec;
/// # }
/// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CString {
inner: Vec<u8>,
}
Expand Down Expand Up @@ -110,13 +113,19 @@ pub struct CString {
/// }
/// ```
#[derive(Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CStr {
// FIXME: this should not be represented with a DST slice but rather with
// just a raw `libc::c_char` along with some form of marker to make
// this an unsized type. Essentially `sizeof(&CStr)` should be the
// same as `sizeof(&c_char)` but `CStr` should be an unsized type.
inner: [libc::c_char]
}

/// An error returned from `CString::new` to indicate that a nul byte was found
/// in the vector provided.
#[derive(Clone, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);

/// A conversion trait used by the constructor of `CString` for types that can
Expand Down Expand Up @@ -153,6 +162,7 @@ impl CString {
/// This function will return an error if the bytes yielded contain an
/// internal 0 byte. The error returned will contain the bytes as well as
/// the position of the nul byte.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<T: IntoBytes>(t: T) -> Result<CString, NulError> {
let bytes = t.into_bytes();
match bytes.iter().position(|x| *x == 0) {
Expand Down Expand Up @@ -216,6 +226,7 @@ impl CString {
///
/// This method is equivalent to `from_vec` except that no runtime assertion
/// is made that `v` contains no 0 bytes.
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
v.push(0);
CString { inner: v }
Expand All @@ -225,17 +236,20 @@ impl CString {
///
/// The returned slice does **not** contain the trailing nul separator and
/// it is guaranteed to not have any interior nul bytes.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn as_bytes(&self) -> &[u8] {
&self.inner[..self.inner.len() - 1]
}

/// Equivalent to the `as_bytes` function except that the returned slice
/// includes the trailing nul byte.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn as_bytes_with_nul(&self) -> &[u8] {
&self.inner
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Deref for CString {
type Target = CStr;

Expand All @@ -254,30 +268,36 @@ impl fmt::Debug for CString {
impl NulError {
/// Returns the position of the nul byte in the slice that was provided to
/// `CString::from_vec`.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn nul_position(&self) -> usize { self.0 }

/// Consumes this error, returning the underlying vector of bytes which
/// generated the error in the first place.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_vec(self) -> Vec<u8> { self.1 }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Error for NulError {
fn description(&self) -> &str { "nul byte found in data" }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for NulError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "nul byte found in provided data at position: {}", self.0)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl FromError<NulError> for io::Error {
fn from_error(_: NulError) -> io::Error {
io::Error::new(io::ErrorKind::InvalidInput,
"data provided contains a nul byte", None)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl FromError<NulError> for old_io::IoError {
fn from_error(_: NulError) -> old_io::IoError {
old_io::IoError {
Expand Down Expand Up @@ -325,6 +345,7 @@ impl CStr {
/// }
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
let len = libc::strlen(ptr);
mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
Expand All @@ -335,6 +356,7 @@ impl CStr {
/// The returned pointer will be valid for as long as `self` is and points
/// to a contiguous region of memory terminated with a 0 byte to represent
/// the end of the string.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn as_ptr(&self) -> *const libc::c_char {
self.inner.as_ptr()
}
Expand All @@ -351,6 +373,7 @@ impl CStr {
/// > **Note**: This method is currently implemented as a 0-cost cast, but
/// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes(&self) -> &[u8] {
let bytes = self.to_bytes_with_nul();
&bytes[..bytes.len() - 1]
Expand All @@ -364,22 +387,27 @@ impl CStr {
/// > **Note**: This method is currently implemented as a 0-cost cast, but
/// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes_with_nul(&self) -> &[u8] {
unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for CStr {
fn eq(&self, other: &CStr) -> bool {
self.to_bytes().eq(other.to_bytes())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for CStr {}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for CStr {
fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
self.to_bytes().partial_cmp(&other.to_bytes())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for CStr {
fn cmp(&self, other: &CStr) -> Ordering {
self.to_bytes().cmp(&other.to_bytes())
Expand Down
11 changes: 7 additions & 4 deletions src/libstd/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,27 @@

//! Utilities related to FFI bindings.

#![unstable(feature = "std_misc",
reason = "module just underwent fairly large reorganization and the dust \
still needs to settle")]
#![stable(feature = "rust1", since = "1.0.0")]

pub use self::c_str::{CString, CStr, NulError, IntoBytes};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CString, CStr};
pub use self::c_str::{NulError, IntoBytes};
#[allow(deprecated)]
pub use self::c_str::c_str_to_bytes;
#[allow(deprecated)]
pub use self::c_str::c_str_to_bytes_with_nul;

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::OsString;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::OsStr;

mod c_str;
mod os_str;

// FIXME (#21670): these should be defined in the os_str module
/// Freely convertible to an `&OsStr` slice.
#[unstable(feature = "std_misc")]
pub trait AsOsStr {
/// Convert to an `&OsStr` slice.
fn as_os_str(&self) -> &OsStr;
Expand Down
Loading

0 comments on commit 628f5d2

Please sign in to comment.