@@ -23,7 +23,7 @@ use ops::Deref;
2323use option:: Option :: { self , Some , None } ;
2424use result:: Result :: { self , Ok , Err } ;
2525use slice;
26- use str;
26+ use str:: { self , Utf8Error } ;
2727use string:: String ;
2828use vec:: Vec ;
2929
@@ -151,6 +151,15 @@ pub struct CStr {
151151#[ stable( feature = "rust1" , since = "1.0.0" ) ]
152152pub struct NulError ( usize , Vec < u8 > ) ;
153153
154+ /// An error returned from `CString::into_string` to indicate that a UTF-8 error
155+ /// was encountered during the conversion.
156+ #[ derive( Clone , PartialEq , Debug ) ]
157+ #[ unstable( feature = "cstring_into" , reason = "recently added" , issue = "29157" ) ]
158+ pub struct IntoStringError {
159+ inner : CString ,
160+ error : Utf8Error ,
161+ }
162+
154163impl CString {
155164 /// Creates a new C-compatible string from a container of bytes.
156165 ///
@@ -255,6 +264,38 @@ impl CString {
255264 Box :: into_raw ( self . inner ) as * mut libc:: c_char
256265 }
257266
267+ /// Converts the `CString` into a `String` if it contains valid Unicode data.
268+ ///
269+ /// On failure, ownership of the original `CString` is returned.
270+ #[ unstable( feature = "cstring_into" , reason = "recently added" , issue = "29157" ) ]
271+ pub fn into_string ( self ) -> Result < String , IntoStringError > {
272+ String :: from_utf8 ( self . into_bytes ( ) )
273+ . map_err ( |e| IntoStringError {
274+ error : e. utf8_error ( ) ,
275+ inner : unsafe { CString :: from_vec_unchecked ( e. into_bytes ( ) ) } ,
276+ } )
277+ }
278+
279+ /// Returns the underlying byte buffer.
280+ ///
281+ /// The returned buffer does **not** contain the trailing nul separator and
282+ /// it is guaranteed to not have any interior nul bytes.
283+ #[ unstable( feature = "cstring_into" , reason = "recently added" , issue = "29157" ) ]
284+ pub fn into_bytes ( self ) -> Vec < u8 > {
285+ // FIXME: Once this method becomes stable, add an `impl Into<Vec<u8>> for CString`
286+ let mut vec = self . inner . into_vec ( ) ;
287+ let _nul = vec. pop ( ) ;
288+ debug_assert_eq ! ( _nul, Some ( 0u8 ) ) ;
289+ vec
290+ }
291+
292+ /// Equivalent to the `into_bytes` function except that the returned vector
293+ /// includes the trailing nul byte.
294+ #[ unstable( feature = "cstring_into" , reason = "recently added" , issue = "29157" ) ]
295+ pub fn into_bytes_with_nul ( self ) -> Vec < u8 > {
296+ self . inner . into_vec ( )
297+ }
298+
258299 /// Returns the contents of this `CString` as a slice of bytes.
259300 ///
260301 /// The returned slice does **not** contain the trailing nul separator and
@@ -336,6 +377,35 @@ impl From<NulError> for io::Error {
336377 }
337378}
338379
380+ impl IntoStringError {
381+ /// Consumes this error, returning original `CString` which generated the
382+ /// error.
383+ #[ unstable( feature = "cstring_into" , reason = "recently added" , issue = "29157" ) ]
384+ pub fn into_cstring ( self ) -> CString {
385+ self . inner
386+ }
387+
388+ /// Access the underlying UTF-8 error that was the cause of this error.
389+ #[ unstable( feature = "cstring_into" , reason = "recently added" , issue = "29157" ) ]
390+ pub fn utf8_error ( & self ) -> Utf8Error {
391+ self . error
392+ }
393+ }
394+
395+ #[ unstable( feature = "cstring_into" , reason = "recently added" , issue = "29157" ) ]
396+ impl Error for IntoStringError {
397+ fn description ( & self ) -> & str {
398+ Error :: description ( & self . error )
399+ }
400+ }
401+
402+ #[ unstable( feature = "cstring_into" , reason = "recently added" , issue = "29157" ) ]
403+ impl fmt:: Display for IntoStringError {
404+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
405+ fmt:: Display :: fmt ( & self . error , f)
406+ }
407+ }
408+
339409impl CStr {
340410 /// Casts a raw C string to a safe C string wrapper.
341411 ///
0 commit comments