Skip to main content

clt_database/alloc/collections/vec/
mod.rs

1#[cfg(nightly)]
2mod nightly;
3
4#[cfg(not(nightly))]
5use super::{
6    TryClone, TursoAllocExt, TursoFromIterator, TursoSliceExt, TursoTryWithCapacityExt,
7    TursoVecExt, TursoVecInExt,
8};
9#[cfg(not(nightly))]
10use crate::alloc::{TryReserveError, Vec};
11
12#[cfg(not(nightly))]
13pub(super) const fn vec<T>() -> Vec<T> {
14    Vec::new()
15}
16
17#[cfg(not(nightly))]
18fn vec_with_capacity<T>(capacity: usize) -> Vec<T> {
19    Vec::with_capacity(capacity)
20}
21
22#[cfg(not(nightly))]
23impl<T> TursoAllocExt for Vec<T> {
24    #[inline(always)]
25    fn new() -> Self {
26        vec()
27    }
28}
29
30#[cfg(not(nightly))]
31impl<T> TursoVecExt<T> for Vec<T> {
32    #[inline(always)]
33    fn with_capacity(capacity: usize) -> Self {
34        vec_with_capacity(capacity)
35    }
36
37    #[inline(always)]
38    fn push_within_capacity(&mut self, value: T) -> Result<&mut T, T> {
39        if self.len() == self.capacity() {
40            return Err(value);
41        }
42
43        unsafe {
44            let end = self.as_mut_ptr().add(self.len());
45            std::ptr::write(end, value);
46            self.set_len(self.len() + 1);
47
48            // SAFETY: We just wrote a value to the pointer that will live the lifetime of the reference.
49            Ok(&mut *end)
50        }
51    }
52
53    #[inline(always)]
54    fn try_push(&mut self, value: T) -> Result<(), TryReserveError> {
55        self.push(value);
56        Ok(())
57    }
58}
59
60#[cfg(not(nightly))]
61impl<T, A> TursoVecInExt<T, A> for Vec<T> {
62    #[inline(always)]
63    fn new_in(_alloc: A) -> Self {
64        vec()
65    }
66
67    #[inline(always)]
68    fn with_capacity_in(capacity: usize, _alloc: A) -> Self {
69        vec_with_capacity(capacity)
70    }
71
72    #[inline(always)]
73    fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, TryReserveError> {
74        Ok(<Self as TursoVecInExt<T, A>>::with_capacity_in(
75            capacity, alloc,
76        ))
77    }
78}
79
80#[cfg(not(nightly))]
81impl<T> TursoTryWithCapacityExt for Vec<T> {
82    #[inline(always)]
83    fn try_with_capacity_ext(capacity: usize) -> Result<Self, TryReserveError> {
84        Ok(vec_with_capacity(capacity))
85    }
86}
87
88#[cfg(not(nightly))]
89impl<T> TursoFromIterator<T> for Vec<T> {
90    #[inline(always)]
91    fn try_from_iter<I>(iter: I) -> Result<Self, TryReserveError>
92    where
93        I: IntoIterator<Item = T>,
94    {
95        Ok(iter.into_iter().collect())
96    }
97
98    #[inline(always)]
99    fn try_extend<I>(&mut self, iter: I) -> Result<(), TryReserveError>
100    where
101        I: IntoIterator<Item = T>,
102    {
103        self.extend(iter);
104        Ok(())
105    }
106}
107
108#[cfg(not(nightly))]
109impl<T: Clone> TursoSliceExt<T> for [T] {
110    #[inline(always)]
111    fn try_to_vec(&self) -> Result<Vec<T>, TryReserveError> {
112        let mut values = <Vec<T> as TursoTryWithCapacityExt>::try_with_capacity_ext(self.len())?;
113        values.extend_from_slice(self);
114        Ok(values)
115    }
116}
117
118#[cfg(not(nightly))]
119impl<T: TryClone> TryClone for Vec<T>
120where
121    TryReserveError: From<T::Error>,
122{
123    type Error = TryReserveError;
124
125    #[inline(always)]
126    fn try_clone(&self) -> Result<Self, Self::Error> {
127        // Same `TryClone` bound as the nightly impl so code compiles
128        // identically on both cfgs. Elements clone through `TryClone`; on
129        // stable this is Clone-forwarded for std-pinned types anyway.
130        //
131        // Write into spare capacity directly instead of `push`: the
132        // per-element capacity check defeats vectorization (6x slower for
133        // Copy elements, 1.7x for non-Copy in alloc_collections benches).
134        // The guard keeps `len` covering exactly the elements written, so an
135        // `Err` from an element clone (or a panic) drops a consistent vec.
136        struct SetLenOnDrop<'a, T> {
137            vec: &'a mut Vec<T>,
138            len: usize,
139        }
140        impl<T> Drop for SetLenOnDrop<'_, T> {
141            #[inline]
142            fn drop(&mut self) {
143                unsafe {
144                    self.vec.set_len(self.len);
145                }
146            }
147        }
148
149        let mut cloned = <Self as TursoTryWithCapacityExt>::try_with_capacity_ext(self.len())?;
150        let ptr = cloned.as_mut_ptr();
151        let mut guard = SetLenOnDrop {
152            vec: &mut cloned,
153            len: 0,
154        };
155        for item in self {
156            let item = item.try_clone()?;
157            unsafe {
158                std::ptr::write(ptr.add(guard.len), item);
159            }
160            guard.len += 1;
161        }
162        drop(guard);
163        Ok(cloned)
164    }
165}