Skip to content

Commit f332c0f

Browse files
Ariel Ben-Yehudaalexcrichton
Ariel Ben-Yehuda
authored andcommitted
Rollup merge of rust-lang#40386 - tbu-:pr_display_frombyteswithnulerror, r=alexcrichton
Distinguish the ways `CStr::from_bytes_with_nul` can fail
2 parents f2e0220 + da6e7c8 commit f332c0f

File tree

1 file changed

+40
-6
lines changed

1 file changed

+40
-6
lines changed

src/libstd/ffi/c_str.rs

+40-6
Original file line numberDiff line numberDiff line change
@@ -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")]
459480
impl 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")]
466492
impl 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

Comments
 (0)