Skip to main content

turbocow/vec/
impls.rs

1use alloc::vec::Vec;
2use core::borrow::Borrow;
3use core::cmp::Ordering;
4use core::hash::{Hash, Hasher};
5use core::ops::Deref;
6use core::ptr;
7
8use super::types::EcoVec;
9use crate::allocator::{AllocatorProvider, Global};
10
11// ── Access ──────────────────────────────────────────────────────────────
12
13impl<T, A> Deref for EcoVec<T, A>
14where
15    A: AllocatorProvider,
16{
17    type Target = [T];
18
19    #[inline]
20    fn deref(&self) -> &Self::Target {
21        self.as_slice()
22    }
23}
24
25impl<T, A> Borrow<[T]> for EcoVec<T, A>
26where
27    A: AllocatorProvider,
28{
29    #[inline]
30    fn borrow(&self) -> &[T] {
31        self.as_slice()
32    }
33}
34
35impl<T, A> AsRef<[T]> for EcoVec<T, A>
36where
37    A: AllocatorProvider,
38{
39    #[inline]
40    fn as_ref(&self) -> &[T] {
41        self.as_slice()
42    }
43}
44
45// ── Comparison ──────────────────────────────────────────────────────────
46
47impl<T, A> Hash for EcoVec<T, A>
48where
49    T: Hash,
50    A: AllocatorProvider,
51{
52    #[inline]
53    fn hash<H: Hasher>(&self, state: &mut H) {
54        self.as_slice().hash(state);
55    }
56}
57
58impl<T, A> Eq for EcoVec<T, A>
59where
60    T: Eq,
61    A: AllocatorProvider,
62{
63}
64
65impl<T, A> PartialEq for EcoVec<T, A>
66where
67    T: PartialEq,
68    A: AllocatorProvider,
69{
70    #[inline]
71    fn eq(&self, other: &Self) -> bool {
72        // Fast-path: two clones sharing the same backing allocation are
73        // trivially equal (same data pointer and same length).
74        (self.ptr == other.ptr && self.len == other.len)
75            || self.as_slice() == other.as_slice()
76    }
77}
78
79impl<T, A> PartialEq<[T]> for EcoVec<T, A>
80where
81    T: PartialEq,
82    A: AllocatorProvider,
83{
84    #[inline]
85    fn eq(&self, other: &[T]) -> bool {
86        self.as_slice() == other
87    }
88}
89
90impl<T, A> PartialEq<&[T]> for EcoVec<T, A>
91where
92    T: PartialEq,
93    A: AllocatorProvider,
94{
95    #[inline]
96    fn eq(&self, other: &&[T]) -> bool {
97        self.as_slice() == *other
98    }
99}
100
101impl<T, A, const N: usize> PartialEq<[T; N]> for EcoVec<T, A>
102where
103    T: PartialEq,
104    A: AllocatorProvider,
105{
106    #[inline]
107    fn eq(&self, other: &[T; N]) -> bool {
108        self.as_slice() == other
109    }
110}
111
112impl<T, A, const N: usize> PartialEq<&[T; N]> for EcoVec<T, A>
113where
114    T: PartialEq,
115    A: AllocatorProvider,
116{
117    #[inline]
118    fn eq(&self, other: &&[T; N]) -> bool {
119        self.as_slice() == *other
120    }
121}
122
123impl<T, A> PartialEq<EcoVec<T, A>> for [T]
124where
125    T: PartialEq,
126    A: AllocatorProvider,
127{
128    #[inline]
129    fn eq(&self, other: &EcoVec<T, A>) -> bool {
130        self == other.as_slice()
131    }
132}
133
134impl<T, A, const N: usize> PartialEq<EcoVec<T, A>> for [T; N]
135where
136    T: PartialEq,
137    A: AllocatorProvider,
138{
139    #[inline]
140    fn eq(&self, other: &EcoVec<T, A>) -> bool {
141        self == other.as_slice()
142    }
143}
144
145impl<T, A> PartialEq<Vec<T>> for EcoVec<T, A>
146where
147    T: PartialEq,
148    A: AllocatorProvider,
149{
150    #[inline]
151    fn eq(&self, other: &Vec<T>) -> bool {
152        self.as_slice() == other.as_slice()
153    }
154}
155
156impl<T, A> PartialEq<EcoVec<T, A>> for Vec<T>
157where
158    T: PartialEq,
159    A: AllocatorProvider,
160{
161    #[inline]
162    fn eq(&self, other: &EcoVec<T, A>) -> bool {
163        self.as_slice() == other.as_slice()
164    }
165}
166
167impl<T, A> Ord for EcoVec<T, A>
168where
169    T: Ord,
170    A: AllocatorProvider,
171{
172    #[inline]
173    fn cmp(&self, other: &Self) -> Ordering {
174        self.as_slice().cmp(other.as_slice())
175    }
176}
177
178impl<T, A> PartialOrd for EcoVec<T, A>
179where
180    T: PartialOrd,
181    A: AllocatorProvider,
182{
183    #[inline]
184    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
185        self.as_slice().partial_cmp(other.as_slice())
186    }
187}
188
189// ── Construction ────────────────────────────────────────────────────────
190
191impl<T> Default for EcoVec<T, Global> {
192    #[inline]
193    fn default() -> Self {
194        Self::new()
195    }
196}
197
198impl<T> From<&[T]> for EcoVec<T, Global>
199where
200    T: Clone,
201{
202    fn from(slice: &[T]) -> Self {
203        let mut vec = Self::with_capacity(slice.len());
204        vec.extend_from_slice(slice);
205        vec
206    }
207}
208
209impl<T, const N: usize> From<[T; N]> for EcoVec<T, Global>
210where
211    T: Clone,
212{
213    fn from(array: [T; N]) -> Self {
214        let mut vec = Self::with_capacity(N);
215        unsafe {
216            // Safety: Array's IntoIter implements `TrustedLen`.
217            vec.extend_from_trusted(array);
218        }
219        vec
220    }
221}
222
223impl<T> From<Vec<T>> for EcoVec<T, Global>
224where
225    T: Clone,
226{
227    /// Allocates a new EcoVec, and moves other's items into it.
228    fn from(mut other: Vec<T>) -> Self {
229        let len = other.len();
230        let mut vec = Self::with_capacity(len);
231        unsafe {
232            // Disables dropping of individual `Vec` items that will be moved
233            // into the `EcoVec`.
234            //
235            // Safety: 0 is less than or equal to capacity.
236            other.set_len(0);
237
238            // Safety:
239            // - The source vector is valid for `len` reads.
240            // - The destination is valid for `len` writes due to the
241            //   `Self::with_capacity(len)` call.
242            // - The source and destination are non-overlapping because we just
243            //   allocated the destination.
244            core::ptr::copy_nonoverlapping(other.as_ptr(), vec.data_mut(), len);
245
246            // Sets the correct length, and thereby also enables dropping of the
247            // individual items that have been moved into the `EcoVec`.
248            // There is no possibility of double dropping because we've already
249            // set the length of the original `Vec` to 0 before copying.
250            vec.len = len;
251        }
252        vec
253    }
254}
255
256impl<T, A, const N: usize> TryFrom<EcoVec<T, A>> for [T; N]
257where
258    T: Clone,
259    A: AllocatorProvider,
260{
261    type Error = EcoVec<T, A>;
262
263    fn try_from(mut vec: EcoVec<T, A>) -> Result<Self, Self::Error> {
264        if vec.len() != N {
265            return Err(vec);
266        }
267
268        Ok(if vec.is_unique() {
269            // Set the length to zero to prevent double drop.
270            vec.len = 0;
271
272            // Safety: We have unique ownership and len == N.
273            unsafe { ptr::read(vec.data() as *const [T; N]) }
274        } else {
275            // Safety: We know that the length is correct.
276            unsafe { core::array::from_fn(|i| vec.get_unchecked(i).clone()) }
277        })
278    }
279}
280
281// ── Iteration ───────────────────────────────────────────────────────────
282
283impl<T, A> Extend<T> for EcoVec<T, A>
284where
285    T: Clone,
286    A: AllocatorProvider + Clone,
287{
288    fn extend<I>(&mut self, iter: I)
289    where
290        I: IntoIterator<Item = T>,
291    {
292        let iter = iter.into_iter();
293        let hint = iter.size_hint().0;
294        if hint > 0 {
295            self.reserve(hint);
296        }
297        // After reserve, we're unique and may have spare capacity.
298        // Use push_unchecked while capacity allows, then fall back to
299        // push (which re-checks unique + grows) only when needed.
300        for value in iter {
301            if self.len < self.capacity() && self.is_unique() {
302                unsafe { self.push_unchecked(value) };
303            } else {
304                self.push(value);
305            }
306        }
307    }
308}
309
310impl<T> FromIterator<T> for EcoVec<T, Global>
311where
312    T: Clone,
313{
314    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
315        let iter = iter.into_iter();
316        let hint = iter.size_hint().0;
317        let mut vec = Self::with_capacity(hint);
318        vec.extend(iter);
319        vec
320    }
321}
322
323impl<'a, T, A> IntoIterator for &'a EcoVec<T, A>
324where
325    A: AllocatorProvider,
326{
327    type IntoIter = core::slice::Iter<'a, T>;
328    type Item = &'a T;
329
330    #[inline]
331    fn into_iter(self) -> Self::IntoIter {
332        self.as_slice().iter()
333    }
334}
335
336impl<T, A> IntoIterator for EcoVec<T, A>
337where
338    T: Clone,
339    A: AllocatorProvider,
340{
341    type IntoIter = IntoIter<T, A>;
342    type Item = T;
343
344    #[inline]
345    fn into_iter(mut self) -> Self::IntoIter {
346        IntoIter {
347            unique: self.is_unique(),
348            front: 0,
349            back: self.len,
350            vec: self,
351        }
352    }
353}
354
355/// An owned iterator over an [`EcoVec`].
356///
357/// If the vector had a reference count of 1, this moves out of the vector,
358/// otherwise it lazily clones.
359///
360/// The second type parameter defaults to [`Global`] so that
361/// `turbocow::vec::IntoIter<T>` resolves without an explicit allocator,
362/// matching ecow's single-parameter `ecow::vec::IntoIter<T>`.
363pub struct IntoIter<T, A = Global>
364where
365    A: AllocatorProvider,
366{
367    vec: EcoVec<T, A>,
368    unique: bool,
369    front: usize,
370    back: usize,
371}
372
373impl<T, A> IntoIter<T, A>
374where
375    A: AllocatorProvider,
376{
377    /// Returns the remaining items of this iterator as a slice.
378    #[inline]
379    pub fn as_slice(&self) -> &[T] {
380        unsafe {
381            core::slice::from_raw_parts(
382                self.vec.data().add(self.front),
383                self.back - self.front,
384            )
385        }
386    }
387}
388
389impl<T, A> Iterator for IntoIter<T, A>
390where
391    T: Clone,
392    A: AllocatorProvider,
393{
394    type Item = T;
395
396    #[inline]
397    fn next(&mut self) -> Option<Self::Item> {
398        (self.front < self.back).then(|| {
399            let prev = self.front;
400            self.front += 1;
401            if self.unique {
402                unsafe { ptr::read(self.vec.data().add(prev)) }
403            } else {
404                unsafe { self.vec.get_unchecked(prev).clone() }
405            }
406        })
407    }
408
409    #[inline]
410    fn size_hint(&self) -> (usize, Option<usize>) {
411        let len = self.back - self.front;
412        (len, Some(len))
413    }
414
415    #[inline]
416    fn count(self) -> usize {
417        self.len()
418    }
419}
420
421impl<T, A> DoubleEndedIterator for IntoIter<T, A>
422where
423    T: Clone,
424    A: AllocatorProvider,
425{
426    #[inline]
427    fn next_back(&mut self) -> Option<Self::Item> {
428        (self.back > self.front).then(|| {
429            self.back -= 1;
430            if self.unique {
431                unsafe { ptr::read(self.vec.data().add(self.back)) }
432            } else {
433                unsafe { self.vec.get_unchecked(self.back).clone() }
434            }
435        })
436    }
437}
438
439impl<T, A> ExactSizeIterator for IntoIter<T, A>
440where
441    T: Clone,
442    A: AllocatorProvider,
443{
444}
445
446impl<T, A> Drop for IntoIter<T, A>
447where
448    A: AllocatorProvider,
449{
450    fn drop(&mut self) {
451        if !self.unique || !self.vec.is_allocated() {
452            return;
453        }
454
455        unsafe {
456            // Set len to zero before dropping to prevent double dropping in
457            // EcoVec's drop impl in case of panic.
458            self.vec.len = 0;
459
460            // Drop only the remaining elements in the middle.
461            ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
462                self.vec.data_mut().add(self.front),
463                self.back - self.front,
464            ));
465        }
466    }
467}
468
469impl<T, A> core::fmt::Debug for IntoIter<T, A>
470where
471    T: core::fmt::Debug,
472    A: AllocatorProvider,
473{
474    #[inline]
475    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
476        f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
477    }
478}