diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index dca1fdde482..ce254f73619 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -1551,6 +1551,27 @@ fn index(&self, _index: ops::RangeFull) -> &CStr { } } +#[stable(feature = "cstr_range_from", since = "1.45.0")] +impl ops::Index> for CStr { + type Output = CStr; + + fn index(&self, index: ops::RangeFrom) -> &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 for CStr { #[inline] @@ -1747,4 +1768,21 @@ fn cstr_const_constructor() { 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()..]; + } }