summaryrefslogtreecommitdiffstats
path: root/library/alloc/src/collections/vec_deque/drain.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/alloc/src/collections/vec_deque/drain.rs')
-rw-r--r--library/alloc/src/collections/vec_deque/drain.rs40
1 files changed, 13 insertions, 27 deletions
diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs
index 89feb361d..0be274a38 100644
--- a/library/alloc/src/collections/vec_deque/drain.rs
+++ b/library/alloc/src/collections/vec_deque/drain.rs
@@ -52,36 +52,22 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> {
}
}
- // Only returns pointers to the slices, as that's
- // all we need to drop them. May only be called if `self.remaining != 0`.
+ // Only returns pointers to the slices, as that's all we need
+ // to drop them. May only be called if `self.remaining != 0`.
unsafe fn as_slices(&self) -> (*mut [T], *mut [T]) {
unsafe {
let deque = self.deque.as_ref();
- // FIXME: This is doing almost exactly the same thing as the else branch in `VecDeque::slice_ranges`.
- // Unfortunately, we can't just call `slice_ranges` here, as the deque's `len` is currently
- // just `drain_start`, so the range check would (almost) always panic. Between temporarily
- // adjusting the deques `len` to call `slice_ranges`, and just copy pasting the `slice_ranges`
- // implementation, this seemed like the less hacky solution, though it might be good to
- // find a better one in the future.
-
- // because `self.remaining != 0`, we know that `self.idx < deque.original_len`, so it's a valid
- // logical index.
- let wrapped_start = deque.to_physical_idx(self.idx);
-
- let head_len = deque.capacity() - wrapped_start;
-
- let (a_range, b_range) = if head_len >= self.remaining {
- (wrapped_start..wrapped_start + self.remaining, 0..0)
- } else {
- let tail_len = self.remaining - head_len;
- (wrapped_start..deque.capacity(), 0..tail_len)
- };
-
- // SAFETY: the range `self.idx..self.idx+self.remaining` lies strictly inside
- // the range `0..deque.original_len`. because of this, and because of the fact
- // that we acquire `a_range` and `b_range` exactly like `slice_ranges` would,
- // it's guaranteed that `a_range` and `b_range` represent valid ranges into
- // the deques buffer.
+
+ // We know that `self.idx + self.remaining <= deque.len <= usize::MAX`, so this won't overflow.
+ let logical_remaining_range = self.idx..self.idx + self.remaining;
+
+ // SAFETY: `logical_remaining_range` represents the
+ // range into the logical buffer of elements that
+ // haven't been drained yet, so they're all initialized,
+ // and `slice::range(start..end, end) == start..end`,
+ // so the preconditions for `slice_ranges` are met.
+ let (a_range, b_range) =
+ deque.slice_ranges(logical_remaining_range.clone(), logical_remaining_range.end);
(deque.buffer_range(a_range), deque.buffer_range(b_range))
}
}