From c0e9a4a5c82afee9d71bf78c3e6a8364fbd40479 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Thu, 24 Sep 2026 14:49:50 +0200 Subject: [PATCH 1/6] refactor: move slice range --- src/lib.rs | 56 +++++++------------------------------------------- src/torange.rs | 47 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 49 deletions(-) create mode 100644 src/torange.rs diff --git a/src/lib.rs b/src/lib.rs index 5434d44f..84ef9b88 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ mod serde; #[cfg(feature = "specialization")] mod specialization; mod taggedlen; +mod torange; #[cfg(not(feature = "allocator-api2"))] use alloc::alloc::{ @@ -82,7 +83,8 @@ use { copy_nonoverlapping, drop_in_place } - } + }, + torange::ToRange }; #[cfg(feature = "internals")] pub use { @@ -95,50 +97,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, 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 len = 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 => len - }; - - if start > end || end > len { - assert_failed(start, end, len); - } - - core::ops::Range { - start, - end - } -} - #[repr(C)] pub struct SmallVec { len: TaggedLen, @@ -662,7 +620,7 @@ impl SmallVec { let core::ops::Range { start, end - } = slice_range(range, ..len); + } = range.to_range(len); unsafe { // SAFETY: `start <= len` @@ -776,7 +734,7 @@ impl SmallVec { let core::ops::Range { start, end - } = slice_range(range, ..old_len); + } = range.to_range(old_len); // Guard against us getting leaked (leak amplification) unsafe { @@ -1545,7 +1503,7 @@ impl SmallVec { R: core::ops::RangeBounds, T: Copy { - let src = slice_range(src, ..self.len()); + let src = src.to_range(self.len()); let core::ops::Range { start, end @@ -1631,7 +1589,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 = src.to_range(self.len()); self.reserve(src.len()); // SAFETY: The call to `reserve` ensures that the capacity is large diff --git a/src/torange.rs b/src/torange.rs new file mode 100644 index 00000000..d9067763 --- /dev/null +++ b/src/torange.rs @@ -0,0 +1,47 @@ +use core::ops::{ + Bound, + Range, + RangeBounds +}; + +pub trait ToRange: RangeBounds + Sized { + fn to_range(self, length: usize) -> Range { + #[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 self.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 self.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 + } + } +} + +impl> ToRange for Type {} From 90ba8adaf09946e9ddd923ad5d36037a4f3635e9 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Thu, 24 Sep 2026 15:00:38 +0200 Subject: [PATCH 2/6] refactor: trait instead --- src/lib.rs | 12 +++---- src/newrange.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ src/torange.rs | 47 ------------------------- 3 files changed, 97 insertions(+), 53 deletions(-) create mode 100644 src/newrange.rs delete mode 100644 src/torange.rs diff --git a/src/lib.rs b/src/lib.rs index b614154e..cfebc4bd 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")] @@ -39,7 +40,6 @@ mod serde; #[cfg(feature = "specialization")] mod specialization; mod taggedlen; -mod torange; #[cfg(feature = "bytes")] use bytes::{ @@ -83,7 +83,7 @@ use { drop_in_place } }, - torange::ToRange + newrange::NewRange }; #[cfg(feature = "internals")] pub use { @@ -442,7 +442,7 @@ impl SmallVec { let core::ops::Range { start, end - } = range.to_range(length); + } = core::ops::Range::new(range, length); unsafe { // SAFETY: `start <= length` @@ -556,7 +556,7 @@ impl SmallVec { let core::ops::Range { start, end - } = range.to_range(old_len); + } = core::ops::Range::new(range, old_len); // Guard against us getting leaked (leak amplification) unsafe { @@ -1311,7 +1311,7 @@ impl SmallVec { R: core::ops::RangeBounds, T: Copy { - let src = src.to_range(self.len()); + let src = core::ops::Range::new(src, self.len()); let core::ops::Range { start, end @@ -1397,7 +1397,7 @@ impl SmallVec { pub fn extend_from_within(&mut self, src: R) where R: core::ops::RangeBounds { - let src = src.to_range(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 00000000..40b004ee --- /dev/null +++ b/src/newrange.rs @@ -0,0 +1,91 @@ +use core::ops::{ + Bound, + Range, + RangeBounds +}; + +pub trait NewRange { + fn new(rangebounds: impl RangeBounds, length: usize) -> Self; +} + +impl NewRange for Range { + 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 + } + } +} + +//pub trait ToRange: RangeBounds + Sized { +// fn to_range(self, length: usize) -> Range { +// #[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 self.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 self.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 +// } +// } +//} +// +//impl> ToRange for Type {} diff --git a/src/torange.rs b/src/torange.rs deleted file mode 100644 index d9067763..00000000 --- a/src/torange.rs +++ /dev/null @@ -1,47 +0,0 @@ -use core::ops::{ - Bound, - Range, - RangeBounds -}; - -pub trait ToRange: RangeBounds + Sized { - fn to_range(self, length: usize) -> Range { - #[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 self.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 self.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 - } - } -} - -impl> ToRange for Type {} From 262754744c1cdd5f7f05fd9a98f226bd5ac80c67 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Thu, 24 Sep 2026 15:01:21 +0200 Subject: [PATCH 3/6] style: formatting --- src/newrange.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/newrange.rs b/src/newrange.rs index 40b004ee..f6663e9c 100644 --- a/src/newrange.rs +++ b/src/newrange.rs @@ -48,7 +48,7 @@ impl NewRange for Range { } } -//pub trait ToRange: RangeBounds + Sized { +// pub trait ToRange: RangeBounds + Sized { // fn to_range(self, length: usize) -> Range { // #[cold] // #[inline(never)] @@ -57,23 +57,23 @@ impl NewRange for Range { // 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}"); -// } +// panic!("range end index {end} out of range for slice of length +// {len}"); } // } // // let start = match self.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 +// .unwrap_or_else(|| panic!("attempted to index slice from after +// maximum usize")), Bound::Unbounded => 0 // }; // // let end = match self.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, +// .unwrap_or_else(|| panic!("attempted to index slice up to +// maximum usize")), Bound::Excluded(&end) => end, // Bound::Unbounded => length // }; // @@ -87,5 +87,4 @@ impl NewRange for Range { // } // } //} -// -//impl> ToRange for Type {} +// impl> ToRange for Type {} From b5eb2718b48c48284d0127c790888ddb58196731 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Thu, 24 Sep 2026 15:02:48 +0200 Subject: [PATCH 4/6] refactor: remove comment --- src/newrange.rs | 43 +------------------------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/src/newrange.rs b/src/newrange.rs index f6663e9c..5b7d600b 100644 --- a/src/newrange.rs +++ b/src/newrange.rs @@ -46,45 +46,4 @@ impl NewRange for Range { end } } -} - -// pub trait ToRange: RangeBounds + Sized { -// fn to_range(self, length: usize) -> Range { -// #[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 self.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 self.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 -// } -// } -//} -// impl> ToRange for Type {} +} \ No newline at end of file From fa4d08662544b0b6f841423bf8898efcda65eeee Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Thu, 24 Sep 2026 15:03:42 +0200 Subject: [PATCH 5/6] feat: add inline to newrange --- src/newrange.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/newrange.rs b/src/newrange.rs index 5b7d600b..57b57d89 100644 --- a/src/newrange.rs +++ b/src/newrange.rs @@ -9,6 +9,7 @@ pub trait NewRange { } impl NewRange for Range { + #[inline] fn new(rangebounds: impl RangeBounds, length: usize) -> Self { #[cold] #[inline(never)] From f9b6b4492ce13945da5ceff027636113cf166cf0 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Thu, 24 Sep 2026 15:24:07 +0200 Subject: [PATCH 6/6] style: formatting --- src/newrange.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/newrange.rs b/src/newrange.rs index 57b57d89..2fcc4b7c 100644 --- a/src/newrange.rs +++ b/src/newrange.rs @@ -47,4 +47,4 @@ impl NewRange for Range { end } } -} \ No newline at end of file +}