Skip to content

std: Stabilize the ffi module #22975

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 7, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're moving away from public tuple structs in std; this should probably be a normal struct with accessors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops nevermind.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I always forget that, unlike enum variants, the pub doesn't automatically extend to tuple components...)


/// 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")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stable reexport?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While not currently recognized by the compiler I've found it useful to see reexports tagged with stability attributes for rustdoc when it doesn't inline documentation and perhaps just helpful when reading code. It doesn't currently serve any semantic purpose though.

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")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why unstable? Just anticipating generic conversion traits?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'm hoping that As<OsStr> will "be the way" to do this in the future.

pub trait AsOsStr {
/// Convert to an `&OsStr` slice.
fn as_os_str(&self) -> &OsStr;
Expand Down
Loading