@@ -15,6 +15,7 @@ use ops::Drop;
15
15
use option:: { Option , Some , None } ;
16
16
use ptr:: RawPtr ;
17
17
use ptr;
18
+ use str;
18
19
use str:: StrSlice ;
19
20
use vec:: { ImmutableVector , CopyableVector } ;
20
21
use container:: Container ;
@@ -97,15 +98,25 @@ impl CString {
97
98
/// # Failure
98
99
///
99
100
/// Fails if the CString is null.
101
+ #[ inline]
100
102
pub fn as_bytes < ' a > ( & ' a self ) -> & ' a [ u8 ] {
101
- #[ fixed_stack_segment] ; #[ inline( never) ] ;
102
103
if self . buf . is_null ( ) { fail ! ( "CString is null!" ) ; }
103
104
unsafe {
104
- let len = libc :: strlen ( self . buf ) as uint ;
105
+ let len = ptr :: position ( self . buf , |c| * c == 0 ) ;
105
106
cast:: transmute ( ( self . buf , len + 1 ) )
106
107
}
107
108
}
108
109
110
+ /// Converts the CString into a `&str` without copying.
111
+ /// Returns None if the CString is not UTF-8 or is null.
112
+ #[ inline]
113
+ pub fn as_str < ' a > ( & ' a self ) -> Option < & ' a str > {
114
+ if self . buf . is_null ( ) { return None ; }
115
+ let buf = self . as_bytes ( ) ;
116
+ let buf = buf. slice_to ( buf. len ( ) -1 ) ; // chop off the trailing NUL
117
+ str:: from_utf8_slice_opt ( buf)
118
+ }
119
+
109
120
/// Return a CString iterator.
110
121
pub fn iter < ' a > ( & ' a self ) -> CStringIterator < ' a > {
111
122
CStringIterator {
@@ -238,7 +249,7 @@ mod tests {
238
249
use option:: { Some , None } ;
239
250
240
251
#[ test]
241
- fn test_to_c_str ( ) {
252
+ fn test_str_to_c_str ( ) {
242
253
do "" . to_c_str ( ) . with_ref |buf| {
243
254
unsafe {
244
255
assert_eq ! ( * ptr:: offset( buf, 0 ) , 0 ) ;
@@ -257,6 +268,37 @@ mod tests {
257
268
}
258
269
}
259
270
271
+ #[ test]
272
+ fn test_vec_to_c_str( ) {
273
+ let b: & [ u8 ] = [ ] ;
274
+ do b. to_c_str ( ) . with_ref |buf| {
275
+ unsafe {
276
+ assert_eq ! ( * ptr:: offset( buf, 0 ) , 0 ) ;
277
+ }
278
+ }
279
+
280
+ do bytes ! ( "hello" ) . to_c_str ( ) . with_ref |buf| {
281
+ unsafe {
282
+ assert_eq ! ( * ptr:: offset( buf, 0 ) , 'h' as libc:: c_char) ;
283
+ assert_eq ! ( * ptr:: offset( buf, 1 ) , 'e' as libc:: c_char) ;
284
+ assert_eq ! ( * ptr:: offset( buf, 2 ) , 'l' as libc:: c_char) ;
285
+ assert_eq ! ( * ptr:: offset( buf, 3 ) , 'l' as libc:: c_char) ;
286
+ assert_eq ! ( * ptr:: offset( buf, 4 ) , 'o' as libc:: c_char) ;
287
+ assert_eq ! ( * ptr:: offset( buf, 5 ) , 0 ) ;
288
+ }
289
+ }
290
+
291
+ do bytes ! ( "foo" , 0xff ) . to_c_str ( ) . with_ref |buf| {
292
+ unsafe {
293
+ assert_eq ! ( * ptr:: offset( buf, 0 ) , 'f' as libc:: c_char) ;
294
+ assert_eq ! ( * ptr:: offset( buf, 1 ) , 'o' as libc:: c_char) ;
295
+ assert_eq ! ( * ptr:: offset( buf, 2 ) , 'o' as libc:: c_char) ;
296
+ assert_eq ! ( * ptr:: offset( buf, 3 ) , 0xff ) ;
297
+ assert_eq ! ( * ptr:: offset( buf, 4 ) , 0 ) ;
298
+ }
299
+ }
300
+ }
301
+
260
302
#[ test]
261
303
fn test_is_null( ) {
262
304
let c_str = unsafe { CString :: new ( ptr:: null ( ) , false ) } ;
@@ -349,4 +391,33 @@ mod tests {
349
391
}
350
392
}
351
393
}
394
+
395
+ #[ test]
396
+ fn test_as_bytes ( ) {
397
+ let c_str = "hello" . to_c_str ( ) ;
398
+ assert_eq ! ( c_str. as_bytes( ) , bytes!( "hello" , 0 ) ) ;
399
+ let c_str = "" . to_c_str ( ) ;
400
+ assert_eq ! ( c_str. as_bytes( ) , bytes!( 0 ) ) ;
401
+ let c_str = bytes ! ( "foo" , 0xff ) . to_c_str ( ) ;
402
+ assert_eq ! ( c_str. as_bytes( ) , bytes!( "foo" , 0xff , 0 ) ) ;
403
+ }
404
+
405
+ #[ test]
406
+ #[ should_fail]
407
+ fn test_as_bytes_fail ( ) {
408
+ let c_str = unsafe { CString :: new ( ptr:: null ( ) , false ) } ;
409
+ c_str. as_bytes ( ) ;
410
+ }
411
+
412
+ #[ test]
413
+ fn test_as_str ( ) {
414
+ let c_str = "hello" . to_c_str ( ) ;
415
+ assert_eq ! ( c_str. as_str( ) , Some ( "hello" ) ) ;
416
+ let c_str = "" . to_c_str ( ) ;
417
+ assert_eq ! ( c_str. as_str( ) , Some ( "" ) ) ;
418
+ let c_str = bytes ! ( "foo" , 0xff ) . to_c_str ( ) ;
419
+ assert_eq ! ( c_str. as_str( ) , None ) ;
420
+ let c_str = unsafe { CString :: new ( ptr:: null ( ) , false ) } ;
421
+ assert_eq ! ( c_str. as_str( ) , None ) ;
422
+ }
352
423
}
0 commit comments