diff --git a/src/lib.rs b/src/lib.rs index 7bdde64..cfebc4b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,7 @@ pub use iterators::{ mod macros; #[cfg(feature = "malloc_size_of")] mod mallocsizeof; +mod newrange; mod rawsmallvec; mod references; #[cfg(feature = "serde")] @@ -81,7 +82,8 @@ use { copy_nonoverlapping, drop_in_place } - } + }, + newrange::NewRange }; #[cfg(feature = "internals")] pub use { @@ -94,50 +96,6 @@ use { taggedlen::TaggedLen }; -#[inline] -/// A local copy of [`core::slice::range`]. The latter function is unstable -/// and thus cannot be used yet. -fn slice_range(range: R, bounds: core::ops::RangeTo) -> core::ops::Range -where R: core::ops::RangeBounds { - #[cold] - #[inline(never)] - #[track_caller] - fn assert_failed(start: usize, end: usize, length: usize) -> ! { - if start > end { - panic!("slice index starts at {start} but ends at {end}"); - } else { - panic!("range end index {end} out of range for slice of length {length}"); - } - } - - let length = bounds.end; - - let start = match range.start_bound() { - core::ops::Bound::Included(&start) => start, - core::ops::Bound::Excluded(start) => start - .checked_add(1) - .unwrap_or_else(|| panic!("attempted to index slice from after maximum usize")), - core::ops::Bound::Unbounded => 0 - }; - - let end = match range.end_bound() { - core::ops::Bound::Included(end) => end - .checked_add(1) - .unwrap_or_else(|| panic!("attempted to index slice up to maximum usize")), - core::ops::Bound::Excluded(&end) => end, - core::ops::Bound::Unbounded => length - }; - - if start > end || end > length { - assert_failed(start, end, length); - } - - core::ops::Range { - start, - end - } -} - #[repr(C)] pub struct SmallVec { length: TaggedLen, @@ -484,7 +442,7 @@ impl SmallVec { let core::ops::Range { start, end - } = slice_range(range, ..length); + } = core::ops::Range::new(range, length); unsafe { // SAFETY: `start <= length` @@ -598,7 +556,7 @@ impl SmallVec { let core::ops::Range { start, end - } = slice_range(range, ..old_len); + } = core::ops::Range::new(range, old_len); // Guard against us getting leaked (leak amplification) unsafe { @@ -1353,7 +1311,7 @@ impl SmallVec { R: core::ops::RangeBounds, T: Copy { - let src = slice_range(src, ..self.len()); + let src = core::ops::Range::new(src, self.len()); let core::ops::Range { start, end @@ -1439,7 +1397,7 @@ impl SmallVec { pub fn extend_from_within(&mut self, src: R) where R: core::ops::RangeBounds { - let src = slice_range(src, ..self.len()); + let src = core::ops::Range::new(src, self.len()); self.reserve(src.len()); // SAFETY: The call to `reserve` ensures that the capacity is large diff --git a/src/newrange.rs b/src/newrange.rs new file mode 100644 index 0000000..2fcc4b7 --- /dev/null +++ b/src/newrange.rs @@ -0,0 +1,50 @@ +use core::ops::{ + Bound, + Range, + RangeBounds +}; + +pub trait NewRange { + fn new(rangebounds: impl RangeBounds, length: usize) -> Self; +} + +impl NewRange for Range { + #[inline] + fn new(rangebounds: impl RangeBounds, length: usize) -> Self { + #[cold] + #[inline(never)] + #[track_caller] + fn assert_failed(start: usize, end: usize, len: usize) -> ! { + if start > end { + panic!("slice index starts at {start} but ends at {end}"); + } else { + panic!("range end index {end} out of range for slice of length {len}"); + } + } + + let start = match rangebounds.start_bound() { + Bound::Included(&start) => start, + Bound::Excluded(start) => start + .checked_add(1) + .unwrap_or_else(|| panic!("attempted to index slice from after maximum usize")), + Bound::Unbounded => 0 + }; + + let end = match rangebounds.end_bound() { + Bound::Included(end) => end + .checked_add(1) + .unwrap_or_else(|| panic!("attempted to index slice up to maximum usize")), + Bound::Excluded(&end) => end, + Bound::Unbounded => length + }; + + if start > end || end > length { + assert_failed(start, end, length); + } + + Range { + start, + end + } + } +}