flex_alloc/vec/
config.rs

1//! `Vec` configuration types and trait definitions.
2
3use core::fmt::Debug;
4use core::marker::PhantomData;
5use core::mem::MaybeUninit;
6use core::ptr::{self, NonNull};
7
8use const_default::ConstDefault;
9
10use crate::alloc::{AllocateIn, Allocator, AllocatorDefault, Fixed, Global, Spill};
11use crate::capacity::{Grow, GrowDoubling, GrowExact, Index};
12use crate::error::StorageError;
13use crate::storage::{ArrayStorage, FatBuffer, Inline, InlineBuffer, SpillStorage, ThinBuffer};
14
15use super::buffer::{VecBuffer, VecHeader};
16
17/// Define the associated types for `Vec` instances.
18pub trait VecConfig {
19    /// The internal buffer type.
20    type Buffer<T>: VecBuffer<Item = T, Index = Self::Index>;
21
22    /// The growth strategy.
23    type Grow: Grow;
24
25    /// The index type used to define the capacity and length.
26    type Index: Index;
27}
28
29impl<A: Allocator> VecConfig for A {
30    type Buffer<T> = FatBuffer<T, VecHeader<usize>, A>;
31    type Grow = GrowDoubling;
32    type Index = usize;
33}
34
35/// Configuration for `Vec` types supporting an allocator.
36pub trait VecConfigAlloc<T>: VecConfig {
37    /// The allocator instance type.
38    type Alloc: Allocator;
39
40    /// Get a reference to the allocator instance.
41    fn allocator(buf: &Self::Buffer<T>) -> &Self::Alloc;
42
43    /// Create a `Vec` buffer instance from its constituent parts.
44    fn buffer_from_parts(
45        data: NonNull<T>,
46        length: Self::Index,
47        capacity: Self::Index,
48        alloc: Self::Alloc,
49    ) -> Self::Buffer<T>;
50
51    /// Disassemble a `Vec` buffer instance into its constituent parts.
52    fn buffer_into_parts(
53        buffer: Self::Buffer<T>,
54    ) -> (NonNull<T>, Self::Index, Self::Index, Self::Alloc);
55}
56
57impl<T, A: Allocator> VecConfigAlloc<T> for A {
58    type Alloc = A;
59
60    #[inline]
61    fn allocator(buf: &Self::Buffer<T>) -> &Self::Alloc {
62        &buf.alloc
63    }
64
65    #[inline]
66    fn buffer_from_parts(
67        data: NonNull<T>,
68        length: Self::Index,
69        capacity: Self::Index,
70        alloc: Self::Alloc,
71    ) -> Self::Buffer<T> {
72        FatBuffer::from_parts(VecHeader { capacity, length }, data, alloc)
73    }
74
75    #[inline]
76    fn buffer_into_parts(
77        buffer: Self::Buffer<T>,
78    ) -> (NonNull<T>, Self::Index, Self::Index, Self::Alloc) {
79        let (header, data, alloc) = buffer.into_parts();
80        (data, header.length, header.capacity, alloc)
81    }
82}
83
84/// Support creation of new `Vec` instances without a storage reference.
85pub trait VecConfigNew<T>: VecConfigSpawn<T> {
86    /// Constant initializer for an empty buffer.
87    const EMPTY_BUFFER: Self::Buffer<T>;
88
89    /// Try to create a new buffer instance with a given capacity.
90    fn buffer_try_new(capacity: Self::Index, exact: bool) -> Result<Self::Buffer<T>, StorageError>;
91}
92
93impl<T, A: AllocatorDefault> VecConfigNew<T> for A {
94    const EMPTY_BUFFER: Self::Buffer<T> = FatBuffer::<T, VecHeader<usize>, A>::DEFAULT;
95
96    #[inline]
97    fn buffer_try_new(capacity: Self::Index, exact: bool) -> Result<Self::Buffer<T>, StorageError> {
98        FatBuffer::allocate_in(
99            VecHeader {
100                capacity,
101                length: Self::Index::ZERO,
102            },
103            A::DEFAULT,
104            exact,
105        )
106    }
107}
108
109/// Support creation of new `Vec` buffer instances from an existing instance.
110pub trait VecConfigSpawn<T>: VecConfig {
111    /// Try to create a new buffer instance with a given capacity.
112    fn buffer_try_spawn(
113        buf: &Self::Buffer<T>,
114        capacity: Self::Index,
115        exact: bool,
116    ) -> Result<Self::Buffer<T>, StorageError>;
117}
118
119impl<T, A: Allocator + Clone> VecConfigSpawn<T> for A {
120    #[inline]
121    fn buffer_try_spawn(
122        buf: &Self::Buffer<T>,
123        capacity: Self::Index,
124        exact: bool,
125    ) -> Result<Self::Buffer<T>, StorageError> {
126        FatBuffer::allocate_in(
127            VecHeader {
128                capacity,
129                length: Index::ZERO,
130            },
131            buf.alloc.clone(),
132            exact,
133        )
134    }
135}
136
137/// Support creation of a new `Vec` instance within an allocation target.
138pub trait VecNewIn<T> {
139    /// The associated `Vec` configuration type.
140    type Config: VecConfig;
141
142    /// Try to create a new buffer given an allocation target.
143    fn buffer_try_new_in(
144        self,
145        capacity: <Self::Config as VecConfig>::Index,
146        exact: bool,
147    ) -> Result<<Self::Config as VecConfig>::Buffer<T>, StorageError>;
148}
149
150/// Parameterize `Vec` with a custom index type or growth behavior.
151#[derive(Debug, Default)]
152pub struct Custom<A: Allocator, I: Index = usize, G: Grow = GrowExact> {
153    alloc: A,
154    _pd: PhantomData<(I, G)>,
155}
156
157impl<A: AllocatorDefault, I: Index, G: Grow> ConstDefault for Custom<A, I, G> {
158    /// An instance of this custom `Vec` definition, which may be used as an allocation target.
159    const DEFAULT: Self = Self {
160        alloc: A::DEFAULT,
161        _pd: PhantomData,
162    };
163}
164
165impl<A: Allocator, I: Index, G: Grow> VecConfig for Custom<A, I, G> {
166    type Buffer<T> = FatBuffer<T, VecHeader<I>, A>;
167    type Grow = G;
168    type Index = I;
169}
170
171impl<T, A: AllocatorDefault, I: Index, G: Grow> VecConfigNew<T> for Custom<A, I, G> {
172    const EMPTY_BUFFER: Self::Buffer<T> = FatBuffer::DEFAULT;
173
174    fn buffer_try_new(capacity: Self::Index, exact: bool) -> Result<Self::Buffer<T>, StorageError> {
175        FatBuffer::allocate_in(
176            VecHeader {
177                capacity,
178                length: Self::Index::ZERO,
179            },
180            A::DEFAULT,
181            exact,
182        )
183    }
184}
185
186impl<T, A: Allocator + Clone, I: Index, G: Grow> VecConfigSpawn<T> for Custom<A, I, G> {
187    #[inline]
188    fn buffer_try_spawn(
189        buf: &Self::Buffer<T>,
190        capacity: Self::Index,
191        exact: bool,
192    ) -> Result<Self::Buffer<T>, StorageError> {
193        FatBuffer::allocate_in(
194            VecHeader {
195                capacity,
196                length: Index::ZERO,
197            },
198            buf.alloc.clone(),
199            exact,
200        )
201    }
202}
203
204/// Parameterize `Vec` with a custom index type or growth behavior.
205#[derive(Clone, Debug, Default, PartialEq, Eq)]
206pub struct Thin<A: Allocator = Global, I: Index = usize, G: Grow = GrowExact> {
207    alloc: A,
208    _pd: PhantomData<(I, G)>,
209}
210
211impl<A: Allocator, I: Index, G: Grow> VecConfig for Thin<A, I, G> {
212    type Buffer<T> = ThinBuffer<T, VecHeader<usize>, A>;
213    type Grow = GrowDoubling;
214    type Index = usize;
215}
216
217impl<A: AllocatorDefault, I: Index, G: Grow> ConstDefault for Thin<A, I, G> {
218    const DEFAULT: Self = Self {
219        alloc: A::DEFAULT,
220        _pd: PhantomData,
221    };
222}
223
224impl<T, A: Allocator, I: Index, G: Grow> VecConfigAlloc<T> for Thin<A, I, G> {
225    type Alloc = A;
226
227    #[inline]
228    fn allocator(buf: &Self::Buffer<T>) -> &Self::Alloc {
229        &buf.alloc
230    }
231
232    #[inline]
233    fn buffer_from_parts(
234        data: NonNull<T>,
235        length: Self::Index,
236        capacity: Self::Index,
237        alloc: Self::Alloc,
238    ) -> Self::Buffer<T> {
239        ThinBuffer::from_parts(VecHeader { capacity, length }, data, alloc)
240    }
241
242    #[inline]
243    fn buffer_into_parts(
244        buffer: Self::Buffer<T>,
245    ) -> (NonNull<T>, Self::Index, Self::Index, Self::Alloc) {
246        let (header, data, alloc) = buffer.into_parts();
247        (data, header.length, header.capacity, alloc)
248    }
249}
250
251impl<T, A: AllocatorDefault, I: Index, G: Grow> VecConfigNew<T> for Thin<A, I, G> {
252    const EMPTY_BUFFER: Self::Buffer<T> = ThinBuffer::<T, VecHeader<usize>, A>::DEFAULT;
253
254    #[inline]
255    fn buffer_try_new(capacity: Self::Index, exact: bool) -> Result<Self::Buffer<T>, StorageError> {
256        ThinBuffer::allocate_in(
257            VecHeader {
258                capacity,
259                length: Self::Index::ZERO,
260            },
261            A::DEFAULT,
262            exact,
263        )
264    }
265}
266
267impl<T, A: Allocator + Clone, I: Index, G: Grow> VecConfigSpawn<T> for Thin<A, I, G> {
268    #[inline]
269    fn buffer_try_spawn(
270        buf: &Self::Buffer<T>,
271        capacity: Self::Index,
272        exact: bool,
273    ) -> Result<Self::Buffer<T>, StorageError> {
274        ThinBuffer::allocate_in(
275            VecHeader {
276                capacity,
277                length: Index::ZERO,
278            },
279            buf.alloc.clone(),
280            exact,
281        )
282    }
283}
284
285impl<T, A: AllocatorDefault, I: Index, G: Grow> VecNewIn<T> for Thin<A, I, G> {
286    type Config = Thin<A, I, G>;
287
288    #[inline]
289    fn buffer_try_new_in(
290        self,
291        capacity: <Self::Config as VecConfig>::Index,
292        exact: bool,
293    ) -> Result<<Self::Config as VecConfig>::Buffer<T>, StorageError> {
294        ThinBuffer::allocate_in(
295            VecHeader {
296                capacity,
297                length: Index::ZERO,
298            },
299            A::DEFAULT,
300            exact,
301        )
302    }
303}
304
305impl<const N: usize> VecConfig for Inline<N> {
306    type Buffer<T> = InlineBuffer<T, N>;
307    type Index = usize;
308    type Grow = GrowExact;
309}
310
311impl<T, const N: usize> VecConfigNew<T> for Inline<N> {
312    const EMPTY_BUFFER: Self::Buffer<T> = InlineBuffer::<T, N>::DEFAULT;
313
314    fn buffer_try_new(capacity: Self::Index, exact: bool) -> Result<Self::Buffer<T>, StorageError> {
315        InlineBuffer::try_for_capacity(capacity, exact)
316    }
317}
318
319impl<T, const N: usize> VecConfigSpawn<T> for Inline<N> {
320    #[inline]
321    fn buffer_try_spawn(
322        _buf: &Self::Buffer<T>,
323        capacity: Self::Index,
324        exact: bool,
325    ) -> Result<Self::Buffer<T>, StorageError> {
326        InlineBuffer::try_for_capacity(capacity, exact)
327    }
328}
329
330impl<T, C: AllocateIn> VecNewIn<T> for C {
331    type Config = C::Alloc;
332
333    #[inline]
334    fn buffer_try_new_in(
335        self,
336        capacity: <Self::Config as VecConfig>::Index,
337        exact: bool,
338    ) -> Result<<Self::Config as VecConfig>::Buffer<T>, StorageError> {
339        FatBuffer::allocate_in(
340            VecHeader {
341                capacity,
342                length: Index::ZERO,
343            },
344            self,
345            exact,
346        )
347    }
348}
349
350impl<T, A: Allocator, I: Index, G: Grow> VecNewIn<T> for Custom<A, I, G> {
351    type Config = Self;
352
353    #[inline]
354    fn buffer_try_new_in(
355        self,
356        capacity: <Self::Config as VecConfig>::Index,
357        exact: bool,
358    ) -> Result<<Self::Config as VecConfig>::Buffer<T>, StorageError> {
359        FatBuffer::allocate_in(
360            VecHeader {
361                capacity,
362                length: Index::ZERO,
363            },
364            self.alloc,
365            exact,
366        )
367    }
368}
369
370impl<'a, T, const N: usize> VecNewIn<T> for &'a mut ArrayStorage<T, N> {
371    type Config = Fixed<'a>;
372
373    #[inline]
374    fn buffer_try_new_in(
375        self,
376        mut capacity: <Self::Config as VecConfig>::Index,
377        exact: bool,
378    ) -> Result<<Self::Config as VecConfig>::Buffer<T>, StorageError> {
379        if capacity > N {
380            return Err(StorageError::CapacityLimit);
381        }
382        if !exact {
383            capacity = N;
384        }
385        Ok(FatBuffer::from_parts(
386            VecHeader {
387                capacity,
388                length: Index::ZERO,
389            },
390            NonNull::from(&mut self.0).cast(),
391            Fixed::default(),
392        ))
393    }
394}
395
396impl<'a, T, A: Allocator> VecNewIn<T> for SpillStorage<'a, &'a mut [MaybeUninit<T>], A> {
397    type Config = Spill<'a, A>;
398
399    fn buffer_try_new_in(
400        self,
401        mut capacity: <Self::Config as VecConfig>::Index,
402        exact: bool,
403    ) -> Result<<Self::Config as VecConfig>::Buffer<T>, StorageError> {
404        if capacity > self.buffer.len() {
405            return FatBuffer::allocate_in(
406                VecHeader {
407                    capacity,
408                    length: Index::ZERO,
409                },
410                Spill::new(self.alloc, ptr::null(), Fixed::DEFAULT),
411                exact,
412            );
413        }
414        if !exact {
415            capacity = self.buffer.len();
416        }
417        let data = NonNull::from(self.buffer).cast::<T>();
418        Ok(FatBuffer::from_parts(
419            VecHeader {
420                capacity,
421                length: Index::ZERO,
422            },
423            data,
424            Spill::new(self.alloc, data.as_ptr().cast::<u8>(), Fixed::DEFAULT),
425        ))
426    }
427}
428
429impl<T, const N: usize> VecNewIn<T> for Inline<N> {
430    type Config = Inline<N>;
431
432    #[inline]
433    fn buffer_try_new_in(
434        self,
435        capacity: <Self::Config as VecConfig>::Index,
436        exact: bool,
437    ) -> Result<<Self::Config as VecConfig>::Buffer<T>, StorageError> {
438        if capacity > N || (capacity < N && exact) {
439            return Err(StorageError::CapacityLimit);
440        }
441        Ok(InlineBuffer::DEFAULT)
442    }
443}