@@ -154,7 +154,28 @@ pub struct NulError(usize, Vec<u8>);
154154/// byte was found too early in the slice provided or one wasn't found at all.
155155#[ derive( Clone , PartialEq , Eq , Debug ) ]
156156#[ 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+ }
158179
159180/// An error returned from `CString::into_string` to indicate that a UTF-8 error
160181/// was encountered during the conversion.
@@ -458,14 +479,23 @@ impl From<NulError> for io::Error {
458479#[ stable( feature = "frombyteswithnulerror_impls" , since = "1.17.0" ) ]
459480impl Error for FromBytesWithNulError {
460481 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+ }
462488 }
463489}
464490
465491#[ stable( feature = "frombyteswithnulerror_impls" , since = "1.17.0" ) ]
466492impl fmt:: Display for FromBytesWithNulError {
467493 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 ( ( ) )
469499 }
470500}
471501
@@ -559,10 +589,14 @@ impl CStr {
559589 #[ stable( feature = "cstr_from_bytes" , since = "1.10.0" ) ]
560590 pub fn from_bytes_with_nul ( bytes : & [ u8 ] )
561591 -> 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) } )
564598 } else {
565- Ok ( unsafe { Self :: from_bytes_with_nul_unchecked ( bytes ) } )
599+ Err ( FromBytesWithNulError :: not_nul_terminated ( ) )
566600 }
567601 }
568602
0 commit comments