X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibstd%2Fffi%2Fc_str.rs;h=89427f7851b389cbbb54599eac953a82e21e6623;hb=2e86485f7b9cc7f4dd702b4cd1c767e12d6d91eb;hp=7c9c2066ae93ae982fb883ce579dd4d8642fa4c7;hpb=f3e6d315386cebdd6679055d9350c258f2a51689;p=rust.git diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 7c9c2066ae9..89427f7851b 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -23,7 +23,7 @@ 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; @@ -151,6 +151,15 @@ pub struct CStr { #[stable(feature = "rust1", since = "1.0.0")] pub struct NulError(usize, Vec); +/// 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. /// @@ -206,7 +215,7 @@ pub unsafe fn from_vec_unchecked(mut v: Vec) -> CString { /// Retakes ownership of a CString that was transferred to C. /// /// The only appropriate argument is a pointer obtained by calling - /// `into_ptr`. The length of the string will be recalculated + /// `into_raw`. The length of the string will be recalculated /// using the pointer. #[unstable(feature = "cstr_memory2", reason = "recently added", issue = "27769")] @@ -245,16 +254,48 @@ pub fn into_ptr(self) -> *const libc::c_char { /// Transfers ownership of the string to a C caller. /// /// The pointer must be returned to Rust and reconstituted using - /// `from_ptr` to be properly deallocated. Specifically, one + /// `from_raw` to be properly deallocated. Specifically, one /// should *not* use the standard C `free` function to deallocate /// this string. /// - /// Failure to call `from_ptr` will lead to a memory leak. + /// Failure to call `from_raw` will lead to a memory leak. #[stable(feature = "cstr_memory", since = "1.4.0")] pub fn into_raw(self) -> *mut libc::c_char { 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::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 { + // FIXME: Once this method becomes stable, add an `impl Into> 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 { + 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 @@ -336,6 +377,35 @@ fn from(_: NulError) -> 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. ///