cl_generic_vec/
raw.rs

1//! The raw vector type that back-up the [`GenericVec`](crate::GenericVec)
2
3use core::mem::MaybeUninit;
4#[cfg(feature = "alloc")]
5use std::boxed::Box;
6
7mod array;
8#[cfg(any(doc, feature = "alloc"))]
9pub(crate) mod heap;
10mod slice;
11
12mod capacity;
13
14/// Error on failure to allocate
15pub struct AllocError;
16/// Result of an allocation
17pub type AllocResult = Result<(), AllocError>;
18
19/// A type that can hold `Self::Item`s, and potentially reserve space for more.
20///
21/// # Safety
22/// Other safe types rely on this trait being implemented correctly.
23/// See the safety requirements on each function
24pub unsafe trait Storage: AsRef<[MaybeUninit<Self::Item>]> + AsMut<[MaybeUninit<Self::Item>]> {
25    /// The type of item that this storage can contain
26    type Item;
27
28    #[doc(hidden)]
29    const CONST_CAPACITY: Option<usize> = None;
30
31    /// Reserves space for at least `new_capacity` elements
32    ///
33    /// # Safety
34    ///
35    /// After this call successfully ends, the `capacity` must be at least
36    /// `new_capacity`
37    ///
38    /// # Panic/Abort
39    ///
40    /// Maybe panic or abort if it is impossible to set the `capacity` to at
41    /// least `new_capacity`
42    fn reserve(&mut self, new_capacity: usize);
43
44    /// Tries to reserve space for at least `new_capacity` elements
45    ///
46    /// # Safety
47    /// If `Ok(())` is returned, the `capacity` must be at least `new_capacity`
48    ///
49    /// # Errors
50    /// If enough space cannot be reserved, returns Err(AllocError)
51    fn try_reserve(&mut self, new_capacity: usize) -> AllocResult;
52}
53
54/// A storage that can be initially created with a given capacity
55///
56/// # Safety
57///
58/// The storage must have a capacity of at least `capacity` after
59/// `StorageWithCapacity::with_capacity` is called.
60pub unsafe trait StorageWithCapacity: Storage + Sized {
61    /// Creates a new storage with at least the given storage capacity
62    fn with_capacity(capacity: usize) -> Self;
63
64    #[doc(hidden)]
65    #[allow(non_snake_case)]
66    fn __with_capacity__const_capacity_checked(capacity: usize, _old_capacity: Option<usize>) -> Self {
67        Self::with_capacity(capacity)
68    }
69}
70
71unsafe impl<S: ?Sized + Storage> Storage for &mut S {
72    type Item = S::Item;
73
74    #[doc(hidden)]
75    const CONST_CAPACITY: Option<usize> = S::CONST_CAPACITY;
76
77    #[inline]
78    fn reserve(&mut self, new_capacity: usize) { S::reserve(self, new_capacity); }
79    #[inline]
80    fn try_reserve(&mut self, new_capacity: usize) -> AllocResult { S::try_reserve(self, new_capacity) }
81}
82
83/// Wrapper for a [`Box<S>`]. Needed to implement some traits that could not be implemented on Box directly
84#[cfg(any(doc, feature = "alloc"))]
85pub struct BoxStorage<S: ?Sized + Storage>(pub Box<S>);
86
87#[cfg(any(doc, feature = "alloc"))]
88impl<S: ?Sized + Storage> AsRef<[MaybeUninit<S::Item>]> for BoxStorage<S> {
89    fn as_ref(&self) -> &[MaybeUninit<S::Item>] { self.0.as_ref().as_ref() }
90}
91
92#[cfg(any(doc, feature = "alloc"))]
93impl<S: ?Sized + Storage> AsMut<[MaybeUninit<S::Item>]> for BoxStorage<S> {
94    fn as_mut(&mut self) -> &mut [MaybeUninit<S::Item>] { self.0.as_mut().as_mut() }
95}
96
97#[cfg(any(doc, feature = "alloc"))]
98unsafe impl<S: ?Sized + Storage> Storage for BoxStorage<S> {
99    type Item = S::Item;
100
101    #[doc(hidden)]
102    const CONST_CAPACITY: Option<usize> = S::CONST_CAPACITY;
103
104    #[inline]
105    fn reserve(&mut self, new_capacity: usize) { S::reserve(&mut self.0, new_capacity); }
106    #[inline]
107    fn try_reserve(&mut self, new_capacity: usize) -> AllocResult { S::try_reserve(&mut self.0, new_capacity) }
108}
109
110#[cfg(any(doc, feature = "alloc"))]
111unsafe impl<S: ?Sized + StorageWithCapacity> StorageWithCapacity for BoxStorage<S> {
112    fn with_capacity(capacity: usize) -> Self { Self(Box::new(S::with_capacity(capacity))) }
113
114    #[doc(hidden)]
115    #[allow(non_snake_case)]
116    fn __with_capacity__const_capacity_checked(capacity: usize, old_capacity: Option<usize>) -> Self {
117        Self(Box::new(S::__with_capacity__const_capacity_checked(
118            capacity,
119            old_capacity,
120        )))
121    }
122}