@@ -23,7 +23,7 @@ use ops::Deref;
23
23
use option:: Option :: { self , Some , None } ;
24
24
use result:: Result :: { self , Ok , Err } ;
25
25
use slice;
26
- use str;
26
+ use str:: { self , Utf8Error } ;
27
27
use string:: String ;
28
28
use vec:: Vec ;
29
29
@@ -151,6 +151,15 @@ pub struct CStr {
151
151
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
152
152
pub struct NulError ( usize , Vec < u8 > ) ;
153
153
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
+
154
163
impl CString {
155
164
/// Creates a new C-compatible string from a container of bytes.
156
165
///
@@ -255,6 +264,38 @@ impl CString {
255
264
Box :: into_raw ( self . inner ) as * mut libc:: c_char
256
265
}
257
266
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
+
258
299
/// Returns the contents of this `CString` as a slice of bytes.
259
300
///
260
301
/// The returned slice does **not** contain the trailing nul separator and
@@ -336,6 +377,35 @@ impl From<NulError> for io::Error {
336
377
}
337
378
}
338
379
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
+
339
409
impl CStr {
340
410
/// Casts a raw C string to a safe C string wrapper.
341
411
///
0 commit comments