about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatt Fellenz <matt@felle.nz>2023-05-30 17:55:16 -0700
committerMatt Fellenz <matt@felle.nz>2023-07-31 11:32:40 -0700
commite12e7fcc500677a76785e5f791be9a637e0b8f4e (patch)
tree621a574ddd46719ef7e275290379e70928d86609
parentb3df56a65f9424a7f4af101091582f49cfc29286 (diff)
downloadrust-e12e7fcc500677a76785e5f791be9a637e0b8f4e.tar.gz
rust-e12e7fcc500677a76785e5f791be9a637e0b8f4e.zip
impl SliceIndex<str> for (Bound<usize>, Bound<usize>)
-rw-r--r--library/core/src/slice/index.rs6
-rw-r--r--library/core/src/slice/mod.rs2
-rw-r--r--library/core/src/str/traits.rs52
3 files changed, 56 insertions, 4 deletions
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index e1e3bcc05e7..d313e8e012f 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -727,7 +727,7 @@ where
 }
 
 /// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
-fn into_range_unchecked(
+pub(crate) fn into_range_unchecked(
     len: usize,
     (start, end): (ops::Bound<usize>, ops::Bound<usize>),
 ) -> ops::Range<usize> {
@@ -747,7 +747,7 @@ fn into_range_unchecked(
 
 /// Convert pair of `ops::Bound`s into `ops::Range`.
 /// Returns `None` on overflowing indices.
-fn into_range(
+pub(crate) fn into_range(
     len: usize,
     (start, end): (ops::Bound<usize>, ops::Bound<usize>),
 ) -> Option<ops::Range<usize>> {
@@ -772,7 +772,7 @@ fn into_range(
 
 /// Convert pair of `ops::Bound`s into `ops::Range`.
 /// Panics on overflowing indices.
-fn into_slice_range(
+pub(crate) fn into_slice_range(
     len: usize,
     (start, end): (ops::Bound<usize>, ops::Bound<usize>),
 ) -> ops::Range<usize> {
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 4f13ea9790d..d95662afddd 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -38,7 +38,7 @@ pub mod sort;
 
 mod ascii;
 mod cmp;
-mod index;
+pub(crate) mod index;
 mod iter;
 mod raw;
 mod rotate;
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 1d52335f28e..a7d7eff609b 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -252,6 +252,58 @@ unsafe impl SliceIndex<str> for ops::Range<usize> {
     }
 }
 
+/// Implements substring slicing for arbitrary bounds.
+///
+/// Returns a slice of the given string bounded by the byte indices
+/// provided by each bound.
+///
+/// This operation is *O*(1).
+///
+/// # Panics
+///
+/// Panics if `begin` or `end` (if it exists and once adjusted for
+/// inclusion/exclusion) does not point to the starting byte offset of
+/// a character (as defined by `is_char_boundary`), if `begin > end`, or if
+/// `end > len`.
+#[stable(feature = "slice_index_str_with_ops_bound_pair", since = "CURRENT_RUSTC_VERSION")]
+unsafe impl SliceIndex<str> for (ops::Bound<usize>, ops::Bound<usize>) {
+    type Output = str;
+
+    #[inline]
+    fn get(self, slice: &str) -> Option<&str> {
+        crate::slice::index::into_range(slice.len(), self)?.get(slice)
+    }
+
+    #[inline]
+    fn get_mut(self, slice: &mut str) -> Option<&mut str> {
+        crate::slice::index::into_range(slice.len(), self)?.get_mut(slice)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked(self, slice: *const str) -> *const str {
+        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
+        unsafe { crate::slice::index::into_range_unchecked(slice.len(), self).get_unchecked(slice) }
+    }
+
+    #[inline]
+    unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut str {
+        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
+        unsafe {
+            crate::slice::index::into_range_unchecked(slice.len(), self).get_unchecked_mut(slice)
+        }
+    }
+
+    #[inline]
+    fn index(self, slice: &str) -> &str {
+        crate::slice::index::into_slice_range(slice.len(), self).index(slice)
+    }
+
+    #[inline]
+    fn index_mut(self, slice: &mut str) -> &mut str {
+        crate::slice::index::into_slice_range(slice.len(), self).index_mut(slice)
+    }
+}
+
 /// Implements substring slicing with syntax `&self[.. end]` or `&mut
 /// self[.. end]`.
 ///