@@ -154,7 +154,28 @@ pub struct NulError(usize, Vec<u8>);
154
154
/// byte was found too early in the slice provided or one wasn't found at all.
155
155
#[ derive( Clone , PartialEq , Eq , Debug ) ]
156
156
#[ stable( feature = "cstr_from_bytes" , since = "1.10.0" ) ]
157
- pub struct FromBytesWithNulError { _a : ( ) }
157
+ pub struct FromBytesWithNulError {
158
+ kind : FromBytesWithNulErrorKind ,
159
+ }
160
+
161
+ #[ derive( Clone , PartialEq , Eq , Debug ) ]
162
+ enum FromBytesWithNulErrorKind {
163
+ InteriorNul ( usize ) ,
164
+ NotNulTerminated ,
165
+ }
166
+
167
+ impl FromBytesWithNulError {
168
+ fn interior_nul ( pos : usize ) -> FromBytesWithNulError {
169
+ FromBytesWithNulError {
170
+ kind : FromBytesWithNulErrorKind :: InteriorNul ( pos) ,
171
+ }
172
+ }
173
+ fn not_nul_terminated ( ) -> FromBytesWithNulError {
174
+ FromBytesWithNulError {
175
+ kind : FromBytesWithNulErrorKind :: NotNulTerminated ,
176
+ }
177
+ }
178
+ }
158
179
159
180
/// An error returned from `CString::into_string` to indicate that a UTF-8 error
160
181
/// was encountered during the conversion.
@@ -458,14 +479,23 @@ impl From<NulError> for io::Error {
458
479
#[ stable( feature = "frombyteswithnulerror_impls" , since = "1.17.0" ) ]
459
480
impl Error for FromBytesWithNulError {
460
481
fn description ( & self ) -> & str {
461
- "data provided is not null terminated or contains an interior nul byte"
482
+ match self . kind {
483
+ FromBytesWithNulErrorKind :: InteriorNul ( ..) =>
484
+ "data provided contains an interior nul byte" ,
485
+ FromBytesWithNulErrorKind :: NotNulTerminated =>
486
+ "data provided is not nul terminated" ,
487
+ }
462
488
}
463
489
}
464
490
465
491
#[ stable( feature = "frombyteswithnulerror_impls" , since = "1.17.0" ) ]
466
492
impl fmt:: Display for FromBytesWithNulError {
467
493
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
468
- self . description ( ) . fmt ( f)
494
+ f. write_str ( self . description ( ) ) ?;
495
+ if let FromBytesWithNulErrorKind :: InteriorNul ( pos) = self . kind {
496
+ write ! ( f, " at byte pos {}" , pos) ?;
497
+ }
498
+ Ok ( ( ) )
469
499
}
470
500
}
471
501
@@ -559,10 +589,14 @@ impl CStr {
559
589
#[ stable( feature = "cstr_from_bytes" , since = "1.10.0" ) ]
560
590
pub fn from_bytes_with_nul ( bytes : & [ u8 ] )
561
591
-> Result < & CStr , FromBytesWithNulError > {
562
- if bytes. is_empty ( ) || memchr:: memchr ( 0 , & bytes) != Some ( bytes. len ( ) - 1 ) {
563
- Err ( FromBytesWithNulError { _a : ( ) } )
592
+ let nul_pos = memchr:: memchr ( 0 , bytes) ;
593
+ if let Some ( nul_pos) = nul_pos {
594
+ if nul_pos + 1 != bytes. len ( ) {
595
+ return Err ( FromBytesWithNulError :: interior_nul ( nul_pos) ) ;
596
+ }
597
+ Ok ( unsafe { CStr :: from_bytes_with_nul_unchecked ( bytes) } )
564
598
} else {
565
- Ok ( unsafe { Self :: from_bytes_with_nul_unchecked ( bytes ) } )
599
+ Err ( FromBytesWithNulError :: not_nul_terminated ( ) )
566
600
}
567
601
}
568
602
0 commit comments