@@ -382,7 +382,7 @@ impl CString {
382
382
let bytes: Vec < u8 > = self . into ( ) ;
383
383
match memchr:: memchr ( 0 , & bytes) {
384
384
Some ( i) => Err ( NulError ( i, bytes) ) ,
385
- None => Ok ( unsafe { CString :: from_vec_unchecked ( bytes) } ) ,
385
+ None => Ok ( unsafe { CString :: _from_vec_unchecked ( bytes) } ) ,
386
386
}
387
387
}
388
388
}
@@ -405,7 +405,7 @@ impl CString {
405
405
// This allows better optimizations if lto enabled.
406
406
match memchr:: memchr ( 0 , bytes) {
407
407
Some ( i) => Err ( NulError ( i, buffer) ) ,
408
- None => Ok ( unsafe { CString :: from_vec_unchecked ( buffer) } ) ,
408
+ None => Ok ( unsafe { CString :: _from_vec_unchecked ( buffer) } ) ,
409
409
}
410
410
}
411
411
@@ -451,10 +451,15 @@ impl CString {
451
451
/// ```
452
452
#[ must_use]
453
453
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
454
- pub unsafe fn from_vec_unchecked ( mut v : Vec < u8 > ) -> CString {
454
+ pub unsafe fn from_vec_unchecked ( v : Vec < u8 > ) -> Self {
455
+ debug_assert ! ( memchr:: memchr( 0 , & v) . is_none( ) ) ;
456
+ unsafe { Self :: _from_vec_unchecked ( v) }
457
+ }
458
+
459
+ unsafe fn _from_vec_unchecked ( mut v : Vec < u8 > ) -> Self {
455
460
v. reserve_exact ( 1 ) ;
456
461
v. push ( 0 ) ;
457
- CString { inner : v. into_boxed_slice ( ) }
462
+ Self { inner : v. into_boxed_slice ( ) }
458
463
}
459
464
460
465
/// Retakes ownership of a `CString` that was transferred to C via
@@ -578,7 +583,7 @@ impl CString {
578
583
pub fn into_string ( self ) -> Result < String , IntoStringError > {
579
584
String :: from_utf8 ( self . into_bytes ( ) ) . map_err ( |e| IntoStringError {
580
585
error : e. utf8_error ( ) ,
581
- inner : unsafe { CString :: from_vec_unchecked ( e. into_bytes ( ) ) } ,
586
+ inner : unsafe { Self :: _from_vec_unchecked ( e. into_bytes ( ) ) } ,
582
587
} )
583
588
}
584
589
@@ -735,6 +740,11 @@ impl CString {
735
740
#[ must_use]
736
741
#[ stable( feature = "cstring_from_vec_with_nul" , since = "1.58.0" ) ]
737
742
pub unsafe fn from_vec_with_nul_unchecked ( v : Vec < u8 > ) -> Self {
743
+ debug_assert ! ( memchr:: memchr( 0 , & v) . unwrap( ) + 1 == v. len( ) ) ;
744
+ unsafe { Self :: _from_vec_with_nul_unchecked ( v) }
745
+ }
746
+
747
+ unsafe fn _from_vec_with_nul_unchecked ( v : Vec < u8 > ) -> Self {
738
748
Self { inner : v. into_boxed_slice ( ) }
739
749
}
740
750
@@ -778,7 +788,7 @@ impl CString {
778
788
Some ( nul_pos) if nul_pos + 1 == v. len ( ) => {
779
789
// SAFETY: We know there is only one nul byte, at the end
780
790
// of the vec.
781
- Ok ( unsafe { Self :: from_vec_with_nul_unchecked ( v) } )
791
+ Ok ( unsafe { Self :: _from_vec_with_nul_unchecked ( v) } )
782
792
}
783
793
Some ( nul_pos) => Err ( FromVecWithNulError {
784
794
error_kind : FromBytesWithNulErrorKind :: InteriorNul ( nul_pos) ,
@@ -811,7 +821,7 @@ impl ops::Deref for CString {
811
821
812
822
#[ inline]
813
823
fn deref ( & self ) -> & CStr {
814
- unsafe { CStr :: from_bytes_with_nul_unchecked ( self . as_bytes_with_nul ( ) ) }
824
+ unsafe { CStr :: _from_bytes_with_nul_unchecked ( self . as_bytes_with_nul ( ) ) }
815
825
}
816
826
}
817
827
@@ -928,7 +938,7 @@ impl From<Vec<NonZeroU8>> for CString {
928
938
} ;
929
939
// SAFETY: `v` cannot contain null bytes, given the type-level
930
940
// invariant of `NonZeroU8`.
931
- CString :: from_vec_unchecked ( v)
941
+ Self :: _from_vec_unchecked ( v)
932
942
}
933
943
}
934
944
}
@@ -1225,7 +1235,7 @@ impl CStr {
1225
1235
unsafe {
1226
1236
let len = sys:: strlen ( ptr) ;
1227
1237
let ptr = ptr as * const u8 ;
1228
- CStr :: from_bytes_with_nul_unchecked ( slice:: from_raw_parts ( ptr, len as usize + 1 ) )
1238
+ Self :: _from_bytes_with_nul_unchecked ( slice:: from_raw_parts ( ptr, len as usize + 1 ) )
1229
1239
}
1230
1240
}
1231
1241
@@ -1268,7 +1278,7 @@ impl CStr {
1268
1278
Some ( nul_pos) if nul_pos + 1 == bytes. len ( ) => {
1269
1279
// SAFETY: We know there is only one nul byte, at the end
1270
1280
// of the byte slice.
1271
- Ok ( unsafe { Self :: from_bytes_with_nul_unchecked ( bytes) } )
1281
+ Ok ( unsafe { Self :: _from_bytes_with_nul_unchecked ( bytes) } )
1272
1282
}
1273
1283
Some ( nul_pos) => Err ( FromBytesWithNulError :: interior_nul ( nul_pos) ) ,
1274
1284
None => Err ( FromBytesWithNulError :: not_nul_terminated ( ) ) ,
@@ -1297,12 +1307,19 @@ impl CStr {
1297
1307
#[ stable( feature = "cstr_from_bytes" , since = "1.10.0" ) ]
1298
1308
#[ rustc_const_stable( feature = "const_cstr_unchecked" , since = "1.59.0" ) ]
1299
1309
pub const unsafe fn from_bytes_with_nul_unchecked ( bytes : & [ u8 ] ) -> & CStr {
1310
+ // We're in a const fn, so this is the best we can do
1311
+ debug_assert ! ( !bytes. is_empty( ) && bytes[ bytes. len( ) - 1 ] == 0 ) ;
1312
+ unsafe { Self :: _from_bytes_with_nul_unchecked ( bytes) }
1313
+ }
1314
+
1315
+ #[ inline]
1316
+ const unsafe fn _from_bytes_with_nul_unchecked ( bytes : & [ u8 ] ) -> & Self {
1300
1317
// SAFETY: Casting to CStr is safe because its internal representation
1301
1318
// is a [u8] too (safe only inside std).
1302
1319
// Dereferencing the obtained pointer is safe because it comes from a
1303
1320
// reference. Making a reference is then safe because its lifetime
1304
1321
// is bound by the lifetime of the given `bytes`.
1305
- unsafe { & * ( bytes as * const [ u8 ] as * const CStr ) }
1322
+ unsafe { & * ( bytes as * const [ u8 ] as * const Self ) }
1306
1323
}
1307
1324
1308
1325
/// Returns the inner pointer to this C string.
@@ -1566,7 +1583,7 @@ impl ops::Index<ops::RangeFrom<usize>> for CStr {
1566
1583
// byte, since otherwise we could get an empty string that doesn't end
1567
1584
// in a null.
1568
1585
if index. start < bytes. len ( ) {
1569
- unsafe { CStr :: from_bytes_with_nul_unchecked ( & bytes[ index. start ..] ) }
1586
+ unsafe { CStr :: _from_bytes_with_nul_unchecked ( & bytes[ index. start ..] ) }
1570
1587
} else {
1571
1588
panic ! (
1572
1589
"index out of bounds: the len is {} but the index is {}" ,
0 commit comments