Skip to content

Owned conversions for CString #28977

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
Oct 19, 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
72 changes: 71 additions & 1 deletion src/libstd/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use ops::Deref;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use slice;
use str;
use str::{self, Utf8Error};
use string::String;
use vec::Vec;

Expand Down Expand Up @@ -151,6 +151,15 @@ pub struct CStr {
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);

/// An error returned from `CString::into_string` to indicate that a UTF-8 error
/// was encountered during the conversion.
#[derive(Clone, PartialEq, Debug)]
#[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
pub struct IntoStringError {
inner: CString,
error: Utf8Error,
}

impl CString {
/// Creates a new C-compatible string from a container of bytes.
///
Expand Down Expand Up @@ -255,6 +264,38 @@ impl CString {
Box::into_raw(self.inner) as *mut libc::c_char
}

/// Converts the `CString` into a `String` if it contains valid Unicode data.
///
/// On failure, ownership of the original `CString` is returned.
#[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
pub fn into_string(self) -> Result<String, IntoStringError> {
String::from_utf8(self.into_bytes())
.map_err(|e| IntoStringError {
error: e.utf8_error(),
inner: unsafe { CString::from_vec_unchecked(e.into_bytes()) },
})
}

/// Returns the underlying byte buffer.
///
/// The returned buffer does **not** contain the trailing nul separator and
/// it is guaranteed to not have any interior nul bytes.
#[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
pub fn into_bytes(self) -> Vec<u8> {
// FIXME: Once this method becomes stable, add an `impl Into<Vec<u8>> for CString`
let mut vec = self.inner.into_vec();
let _nul = vec.pop();
debug_assert_eq!(_nul, Some(0u8));
vec
}

/// Equivalent to the `into_bytes` function except that the returned vector
/// includes the trailing nul byte.
#[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
pub fn into_bytes_with_nul(self) -> Vec<u8> {
self.inner.into_vec()
}

/// Returns the contents of this `CString` as a slice of bytes.
///
/// The returned slice does **not** contain the trailing nul separator and
Expand Down Expand Up @@ -336,6 +377,35 @@ impl From<NulError> for io::Error {
}
}

impl IntoStringError {
/// Consumes this error, returning original `CString` which generated the
/// error.
#[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
pub fn into_cstring(self) -> CString {
self.inner
}

/// Access the underlying UTF-8 error that was the cause of this error.
#[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
pub fn utf8_error(&self) -> Utf8Error {
self.error
}
}

#[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
impl Error for IntoStringError {
fn description(&self) -> &str {
Error::description(&self.error)
}
}

#[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
impl fmt::Display for IntoStringError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.error, f)
}
}

impl CStr {
/// Casts a raw C string to a safe C string wrapper.
///
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#![stable(feature = "rust1", since = "1.0.0")]

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

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