Skip to main content

alloc/collections/vec_deque/
spec_extend.rs

1use core::iter::{Copied, Rev, TrustedLen};
2use core::slice;
3
4use super::{Drain, VecDeque};
5use crate::alloc::Allocator;
6#[cfg(not(test))]
7use crate::vec;
8
9// Specialization trait used for VecDeque::extend
10pub(super) trait SpecExtend<T, I> {
11    fn spec_extend(&mut self, iter: I);
12}
13
14impl<T, I, A: Allocator> SpecExtend<T, I> for VecDeque<T, A>
15where
16    I: Iterator<Item = T>,
17{
18    default fn spec_extend(&mut self, mut iter: I) {
19        // This function should be the moral equivalent of:
20        //
21        // for item in iter {
22        //     self.push_back(item);
23        // }
24
25        while let Some(element) = iter.next() {
26            let (lower, _) = iter.size_hint();
27            self.reserve(lower.saturating_add(1));
28
29            // SAFETY: We just reserved space for at least one element.
30            unsafe { self.push_unchecked(element) };
31
32            // Inner loop to avoid repeatedly calling `reserve`.
33            while self.len < self.capacity() {
34                let Some(element) = iter.next() else {
35                    return;
36                };
37                // SAFETY: The loop condition guarantees that `self.len() < self.capacity()`.
38                unsafe { self.push_unchecked(element) };
39            }
40        }
41    }
42}
43
44impl<T, I, A: Allocator> SpecExtend<T, I> for VecDeque<T, A>
45where
46    I: TrustedLen<Item = T>,
47{
48    default fn spec_extend(&mut self, iter: I) {
49        // This is the case for a TrustedLen iterator.
50        let (low, high) = iter.size_hint();
51        if let Some(additional) = high {
52            if true {
    {
        match (&low, &additional) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val,
                        ::core::option::Option::Some(format_args!("TrustedLen iterator\'s size hint is not exact: {0:?}",
                                (low, high))));
                }
            }
        }
    };
};debug_assert_eq!(
53                low,
54                additional,
55                "TrustedLen iterator's size hint is not exact: {:?}",
56                (low, high)
57            );
58            self.reserve(additional);
59
60            // ignore-tidy-undocumented-unsafe
61            let written = unsafe {
62                self.write_iter_wrapping(self.to_wrapped_index(self.len), iter, additional)
63            };
64
65            if true {
    {
        match (&additional, &written) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val,
                        ::core::option::Option::Some(format_args!("The number of items written to VecDeque doesn\'t match the TrustedLen size hint")));
                }
            }
        }
    };
};debug_assert_eq!(
66                additional, written,
67                "The number of items written to VecDeque doesn't match the TrustedLen size hint"
68            );
69        } else {
70            // Per TrustedLen contract a `None` upper bound means that the iterator length
71            // truly exceeds usize::MAX, which would eventually lead to a capacity overflow anyway.
72            // Since the other branch already panics eagerly (via `reserve()`) we do the same here.
73            // This avoids additional codegen for a fallback code path which would eventually
74            // panic anyway.
75            { ::core::panicking::panic_fmt(format_args!("capacity overflow")); };panic!("capacity overflow");
76        }
77    }
78}
79
80#[cfg(not(test))]
81impl<T, A1: Allocator, A2: Allocator> SpecExtend<T, vec::IntoIter<T, A2>> for VecDeque<T, A1> {
82    fn spec_extend(&mut self, iterator: vec::IntoIter<T, A2>) {
83        let slice = iterator.as_slice();
84        self.reserve(slice.len());
85
86        // ignore-tidy-undocumented-unsafe
87        unsafe {
88            self.copy_slice(self.to_wrapped_index(self.len), slice);
89            self.len += slice.len();
90        }
91        iterator.forget_remaining_elements_and_dealloc();
92    }
93}
94
95impl<'a, T: 'a, I, A: Allocator> SpecExtend<&'a T, I> for VecDeque<T, A>
96where
97    I: Iterator<Item = &'a T>,
98    T: Copy,
99{
100    default fn spec_extend(&mut self, iterator: I) {
101        self.spec_extend(iterator.copied())
102    }
103}
104
105impl<'a, T: 'a, A: Allocator> SpecExtend<&'a T, slice::Iter<'a, T>> for VecDeque<T, A>
106where
107    T: Copy,
108{
109    fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) {
110        let slice = iterator.as_slice();
111        self.reserve(slice.len());
112
113        // ignore-tidy-undocumented-unsafe
114        unsafe {
115            self.copy_slice(self.to_wrapped_index(self.len), slice);
116            self.len += slice.len();
117        }
118    }
119}
120
121// Specialization trait used for VecDeque::extend_front
122pub(super) trait SpecExtendFront<T, I> {
123    #[track_caller]
124    fn spec_extend_front(&mut self, iter: I);
125}
126
127impl<T, I, A: Allocator> SpecExtendFront<T, I> for VecDeque<T, A>
128where
129    I: Iterator<Item = T>,
130{
131    #[track_caller]
132    default fn spec_extend_front(&mut self, mut iter: I) {
133        // This function should be the moral equivalent of:
134        //
135        // for item in iter {
136        //     self.push_front(item);
137        // }
138
139        while let Some(element) = iter.next() {
140            let (lower, _) = iter.size_hint();
141            self.reserve(lower.saturating_add(1));
142
143            // SAFETY: We just reserved space for at least one element.
144            unsafe { self.push_front_unchecked(element) };
145
146            // Inner loop to avoid repeatedly calling `reserve`.
147            while self.len < self.capacity() {
148                let Some(element) = iter.next() else {
149                    return;
150                };
151                // SAFETY: The loop condition guarantees that `self.len() < self.capacity()`.
152                unsafe { self.push_front_unchecked(element) };
153            }
154        }
155    }
156}
157
158#[cfg(not(test))]
159impl<T, A1: Allocator, A2: Allocator> SpecExtendFront<T, vec::IntoIter<T, A2>> for VecDeque<T, A1> {
160    #[track_caller]
161    fn spec_extend_front(&mut self, iterator: vec::IntoIter<T, A2>) {
162        let slice = iterator.as_slice();
163        self.reserve(slice.len());
164        // SAFETY: `slice.len()` space was just reserved and elements in the slice are forgotten after this call
165        unsafe { prepend_reversed(self, slice) };
166        iterator.forget_remaining_elements_and_dealloc();
167    }
168}
169
170#[cfg(not(test))]
171impl<T, A1: Allocator, A2: Allocator> SpecExtendFront<T, Rev<vec::IntoIter<T, A2>>>
172    for VecDeque<T, A1>
173{
174    #[track_caller]
175    fn spec_extend_front(&mut self, iterator: Rev<vec::IntoIter<T, A2>>) {
176        let iterator = iterator.into_inner();
177        let slice = iterator.as_slice();
178        self.reserve(slice.len());
179        // SAFETY: `slice.len()` space was just reserved and elements in the slice are forgotten after this call
180        unsafe { prepend(self, slice) };
181        iterator.forget_remaining_elements_and_dealloc();
182    }
183}
184
185impl<'a, T, A: Allocator> SpecExtendFront<T, Copied<slice::Iter<'a, T>>> for VecDeque<T, A>
186where
187    Copied<slice::Iter<'a, T>>: Iterator<Item = T>,
188{
189    #[track_caller]
190    fn spec_extend_front(&mut self, iter: Copied<slice::Iter<'a, T>>) {
191        let slice = iter.into_inner().as_slice();
192        self.reserve(slice.len());
193        // SAFETY: `slice.len()` space was just reserved and T is Copy because Copied<slice::Iter<'a, T>> is Iterator
194        unsafe { prepend_reversed(self, slice) };
195    }
196}
197
198impl<'a, T, A: Allocator> SpecExtendFront<T, Rev<Copied<slice::Iter<'a, T>>>> for VecDeque<T, A>
199where
200    Rev<Copied<slice::Iter<'a, T>>>: Iterator<Item = T>,
201{
202    #[track_caller]
203    fn spec_extend_front(&mut self, iter: Rev<Copied<slice::Iter<'a, T>>>) {
204        let slice = iter.into_inner().into_inner().as_slice();
205        self.reserve(slice.len());
206        // SAFETY: `slice.len()` space was just reserved and T is Copy because Rev<Copied<slice::Iter<'a, T>>> is Iterator
207        unsafe { prepend(self, slice) };
208    }
209}
210
211impl<'a, T, A1: Allocator, A2: Allocator> SpecExtendFront<T, Drain<'a, T, A2>> for VecDeque<T, A1> {
212    #[track_caller]
213    fn spec_extend_front(&mut self, mut iter: Drain<'a, T, A2>) {
214        if iter.remaining == 0 {
215            return;
216        }
217
218        self.reserve(iter.remaining);
219
220        // SAFETY: iter.remaining != 0.
221        let (left, right) = unsafe { iter.as_slices() };
222        // SAFETY:
223        // - `iter.remaining` space was reserved, `iter.remaining == left.len() + right.len()`.
224        // - The elements in `left` and `right` are forgotten after these calls.
225        unsafe {
226            prepend_reversed(self, &*left);
227            prepend_reversed(self, &*right)
228        };
229
230        iter.idx += iter.remaining;
231        iter.remaining = 0;
232    }
233}
234
235impl<'a, T, A1: Allocator, A2: Allocator> SpecExtendFront<T, Rev<Drain<'a, T, A2>>>
236    for VecDeque<T, A1>
237{
238    #[track_caller]
239    fn spec_extend_front(&mut self, iter: Rev<Drain<'a, T, A2>>) {
240        let mut iter = iter.into_inner();
241
242        if iter.remaining == 0 {
243            return;
244        }
245
246        self.reserve(iter.remaining);
247
248        // SAFETY: iter.remaining != 0.
249        let (left, right) = unsafe { iter.as_slices() };
250        // SAFETY:
251        // - `iter.remaining` space was reserved, `iter.remaining == left.len() + right.len()`.
252        // - The elements in `left` and `right` are forgotten after these calls.
253        unsafe {
254            prepend(self, &*right);
255            prepend(self, &*left);
256        }
257
258        iter.idx += iter.remaining;
259        iter.remaining = 0;
260    }
261}
262
263/// Prepends elements of `slice` to `deque` using a copy.
264///
265/// # Safety
266///
267/// - `deque` must have space for `slice.len()` new elements.
268/// - Elements of `slice` will be copied into the deque, make sure to forget the elements if `T` is not `Copy`.
269unsafe fn prepend<T, A: Allocator>(deque: &mut VecDeque<T, A>, slice: &[T]) {
270    // SAFETY: Upheld by caller.
271    unsafe {
272        deque.head = deque.wrap_sub(deque.head, slice.len());
273        deque.copy_slice(deque.head, slice);
274        deque.len += slice.len();
275    }
276}
277
278/// Prepends elements of `slice` to `deque` in reverse order using a copy.
279///
280/// # Safety
281///
282/// - `deque` must have space for `slice.len()` new elements.
283/// - Elements of `slice` will be copied into the deque, make sure to forget the elements if `T` is not `Copy`.
284unsafe fn prepend_reversed<T, A: Allocator>(deque: &mut VecDeque<T, A>, slice: &[T]) {
285    // SAFETY: Upheld by caller.
286    unsafe {
287        deque.head = deque.wrap_sub(deque.head, slice.len());
288        deque.copy_slice_reversed(deque.head, slice);
289        deque.len += slice.len();
290    }
291}