diff options
| author | Tobias Bucher <tobiasbucher5991@gmail.com> | 2017-03-09 13:31:26 +0100 |
|---|---|---|
| committer | Tobias Bucher <tobiasbucher5991@gmail.com> | 2017-03-09 13:31:55 +0100 |
| commit | da6e7c8f3aa97602bf1bf67b8389c7d3ef3fe11e (patch) | |
| tree | 5c3f2aecef9c50438c6d61299d9ca88ecbf23e04 /src/libstd/ffi | |
| parent | b04ebef43242ade6be8968694caf56a0fb00a4d3 (diff) | |
| download | rust-da6e7c8f3aa97602bf1bf67b8389c7d3ef3fe11e.tar.gz rust-da6e7c8f3aa97602bf1bf67b8389c7d3ef3fe11e.zip | |
Distinguish the ways `CStr::from_bytes_with_nul` can fail
Diffstat (limited to 'src/libstd/ffi')
| -rw-r--r-- | src/libstd/ffi/c_str.rs | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index bc678fcb838..bfb0aa6e1a1 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -154,7 +154,28 @@ pub struct NulError(usize, Vec<u8>); /// byte was found too early in the slice provided or one wasn't found at all. #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "cstr_from_bytes", since = "1.10.0")] -pub struct FromBytesWithNulError { _a: () } +pub struct FromBytesWithNulError { + kind: FromBytesWithNulErrorKind, +} + +#[derive(Clone, PartialEq, Eq, Debug)] +enum FromBytesWithNulErrorKind { + InteriorNul(usize), + NotNulTerminated, +} + +impl FromBytesWithNulError { + fn interior_nul(pos: usize) -> FromBytesWithNulError { + FromBytesWithNulError { + kind: FromBytesWithNulErrorKind::InteriorNul(pos), + } + } + fn not_nul_terminated() -> FromBytesWithNulError { + FromBytesWithNulError { + kind: FromBytesWithNulErrorKind::NotNulTerminated, + } + } +} /// An error returned from `CString::into_string` to indicate that a UTF-8 error /// was encountered during the conversion. @@ -458,14 +479,23 @@ impl From<NulError> for io::Error { #[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] impl Error for FromBytesWithNulError { fn description(&self) -> &str { - "data provided is not null terminated or contains an interior nul byte" + match self.kind { + FromBytesWithNulErrorKind::InteriorNul(..) => + "data provided contains an interior nul byte", + FromBytesWithNulErrorKind::NotNulTerminated => + "data provided is not nul terminated", + } } } #[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] impl fmt::Display for FromBytesWithNulError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) + f.write_str(self.description())?; + if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind { + write!(f, " at byte pos {}", pos)?; + } + Ok(()) } } @@ -559,10 +589,14 @@ impl CStr { #[stable(feature = "cstr_from_bytes", since = "1.10.0")] pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> { - if bytes.is_empty() || memchr::memchr(0, &bytes) != Some(bytes.len() - 1) { - Err(FromBytesWithNulError { _a: () }) + let nul_pos = memchr::memchr(0, bytes); + if let Some(nul_pos) = nul_pos { + if nul_pos + 1 != bytes.len() { + return Err(FromBytesWithNulError::interior_nul(nul_pos)); + } + Ok(unsafe { CStr::from_bytes_with_nul_unchecked(bytes) }) } else { - Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) + Err(FromBytesWithNulError::not_nul_terminated()) } } |
