@@ -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
@@ -922,7 +932,7 @@ impl From<Vec<NonZeroU8>> for CString {
922
932
} ;
923
933
// SAFETY: `v` cannot contain null bytes, given the type-level
924
934
// invariant of `NonZeroU8`.
925
- CString :: from_vec_unchecked ( v)
935
+ Self :: _from_vec_unchecked ( v)
926
936
}
927
937
}
928
938
}
@@ -1215,7 +1225,7 @@ impl CStr {
1215
1225
unsafe {
1216
1226
let len = sys:: strlen ( ptr) ;
1217
1227
let ptr = ptr as * const u8 ;
1218
- CStr :: from_bytes_with_nul_unchecked ( slice:: from_raw_parts ( ptr, len as usize + 1 ) )
1228
+ Self :: _from_bytes_with_nul_unchecked ( slice:: from_raw_parts ( ptr, len as usize + 1 ) )
1219
1229
}
1220
1230
}
1221
1231
@@ -1258,7 +1268,7 @@ impl CStr {
1258
1268
Some ( nul_pos) if nul_pos + 1 == bytes. len ( ) => {
1259
1269
// SAFETY: We know there is only one nul byte, at the end
1260
1270
// of the byte slice.
1261
- Ok ( unsafe { Self :: from_bytes_with_nul_unchecked ( bytes) } )
1271
+ Ok ( unsafe { Self :: _from_bytes_with_nul_unchecked ( bytes) } )
1262
1272
}
1263
1273
Some ( nul_pos) => Err ( FromBytesWithNulError :: interior_nul ( nul_pos) ) ,
1264
1274
None => Err ( FromBytesWithNulError :: not_nul_terminated ( ) ) ,
@@ -1287,12 +1297,19 @@ impl CStr {
1287
1297
#[ stable( feature = "cstr_from_bytes" , since = "1.10.0" ) ]
1288
1298
#[ rustc_const_stable( feature = "const_cstr_unchecked" , since = "1.59.0" ) ]
1289
1299
pub const unsafe fn from_bytes_with_nul_unchecked ( bytes : & [ u8 ] ) -> & CStr {
1300
+ // We're in a const fn, so this is the best we can do
1301
+ debug_assert ! ( !bytes. is_empty( ) && bytes[ bytes. len( ) - 1 ] == 0 ) ;
1302
+ unsafe { Self :: _from_bytes_with_nul_unchecked ( bytes) }
1303
+ }
1304
+
1305
+ #[ inline]
1306
+ const unsafe fn _from_bytes_with_nul_unchecked ( bytes : & [ u8 ] ) -> & Self {
1290
1307
// SAFETY: Casting to CStr is safe because its internal representation
1291
1308
// is a [u8] too (safe only inside std).
1292
1309
// Dereferencing the obtained pointer is safe because it comes from a
1293
1310
// reference. Making a reference is then safe because its lifetime
1294
1311
// is bound by the lifetime of the given `bytes`.
1295
- unsafe { & * ( bytes as * const [ u8 ] as * const CStr ) }
1312
+ unsafe { & * ( bytes as * const [ u8 ] as * const Self ) }
1296
1313
}
1297
1314
1298
1315
/// Returns the inner pointer to this C string.
@@ -1555,7 +1572,7 @@ impl ops::Index<ops::RangeFrom<usize>> for CStr {
1555
1572
// byte, since otherwise we could get an empty string that doesn't end
1556
1573
// in a null.
1557
1574
if index. start < bytes. len ( ) {
1558
- unsafe { CStr :: from_bytes_with_nul_unchecked ( & bytes[ index. start ..] ) }
1575
+ unsafe { CStr :: _from_bytes_with_nul_unchecked ( & bytes[ index. start ..] ) }
1559
1576
} else {
1560
1577
panic ! (
1561
1578
"index out of bounds: the len is {} but the index is {}" ,
0 commit comments