1
Fork 0

Rollup merge of #74021 - 1011X:master, r=dtolnay

impl Index<RangeFrom> for CStr

This change implements (partial) slicing for `CStr`.

Since a `CStr` must end in a null byte, it's not possible to trim from the right and still have a valid `CStr`. But, it *is* possible to trim from the left. This lets us be a bit more flexible and treat them more like strings.

```rust
let string = CStr::from_bytes_with_nul(b"Hello World!\0");
let result = CStr::from_bytes_with_nul(b"World!\0");
assert_eq!(&string[6..], result);
```
This commit is contained in:
Manish Goregaokar 2020-07-18 16:50:54 -07:00 committed by GitHub
commit f305b200df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1551,6 +1551,27 @@ impl ops::Index<ops::RangeFull> for CString {
}
}
#[stable(feature = "cstr_range_from", since = "1.47.0")]
impl ops::Index<ops::RangeFrom<usize>> for CStr {
type Output = CStr;
fn index(&self, index: ops::RangeFrom<usize>) -> &CStr {
let bytes = self.to_bytes_with_nul();
// we need to manually check the starting index to account for the null
// byte, since otherwise we could get an empty string that doesn't end
// in a null.
if index.start < bytes.len() {
unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) }
} else {
panic!(
"index out of bounds: the len is {} but the index is {}",
bytes.len(),
index.start
);
}
}
}
#[stable(feature = "cstring_asref", since = "1.7.0")]
impl AsRef<CStr> for CStr {
#[inline]
@ -1747,4 +1768,21 @@ mod tests {
assert_eq!(CSTR.to_str().unwrap(), "Hello, world!");
}
#[test]
fn cstr_index_from() {
let original = b"Hello, world!\0";
let cstr = CStr::from_bytes_with_nul(original).unwrap();
let result = CStr::from_bytes_with_nul(&original[7..]).unwrap();
assert_eq!(&cstr[7..], result);
}
#[test]
#[should_panic]
fn cstr_index_from_empty() {
let original = b"Hello, world!\0";
let cstr = CStr::from_bytes_with_nul(original).unwrap();
let _ = &cstr[original.len()..];
}
}