tiny_vec/
raw.rs

1#[cfg(feature = "alloc")]
2extern crate alloc as _alloc;
3#[cfg(feature = "alloc")]
4use _alloc::alloc::{self,Layout};
5
6use core::mem;
7use core::ptr::NonNull;
8
9pub struct RawVec<T> {
10    pub ptr: NonNull<T>,
11    pub cap: usize,
12}
13
14/// Returns the next capacity value
15#[inline(always)]
16#[cfg(feature = "alloc")]
17const fn next_cap(cap: usize) -> usize {
18    if cap == 0 { 1 } else { cap * 2 }
19}
20
21impl<T: Sized> RawVec<T> {
22    pub fn new() -> Self {
23        let cap = if mem::size_of::<T>() == 0 { isize::MAX } else { 0 };
24        Self {
25            ptr: NonNull::dangling(),
26            cap: cap as usize,
27        }
28    }
29}
30
31/// Represents an error when trying to allocate memory
32#[derive(Debug,Clone,Copy,PartialEq)]
33pub enum ResizeError {
34    #[cfg(feature = "alloc")]
35    AllocationError(Layout),
36    #[cfg(not(feature = "alloc"))]
37    AllocNotSupported,
38    CapacityOverflow,
39    AllocationExceedsMaximun,
40}
41
42impl ResizeError {
43    pub (crate) fn handle(&self) -> ! {
44        #[cfg(feature = "alloc")]
45        if let Self::AllocationError(layout) = self {
46            alloc::handle_alloc_error(*layout)
47        }
48        #[cfg(not(feature = "alloc"))]
49        if let Self::AllocNotSupported = self {
50            panic!("Alloc is not enabled. Can't switch the buffer to the heap")
51        }
52        panic!("Fatal error: {self:?}");
53    }
54}
55
56#[cfg(feature = "alloc")]
57impl<T: Sized> RawVec<T> {
58    pub fn try_with_capacity(cap: usize) -> Result<Self,ResizeError> {
59        let mut vec = Self::new();
60        if mem::size_of::<T>() != 0 {
61            vec.resize_buffer(cap)?;
62        }
63        Ok(vec)
64    }
65    fn resize_buffer(&mut self, new_cap: usize) -> Result<(), ResizeError> {
66        // since we set the capacity to usize::MAX when T has size 0,
67        // getting to here necessarily means the Vec is overfull.
68        if mem::size_of::<T>() == 0 {
69            return Err(ResizeError::CapacityOverflow)
70        }
71
72        let Ok(new_layout) = Layout::array::<T>(new_cap) else {
73            return Err(ResizeError::AllocationExceedsMaximun);
74        };
75        if new_layout.size() > isize::MAX as usize {
76            return Err(ResizeError::AllocationExceedsMaximun);
77        }
78
79        let new_ptr = if self.cap == 0 {
80            unsafe { alloc::alloc(new_layout) }
81        } else {
82            let old_layout = Layout::array::<T>(self.cap).unwrap();
83            let ptr = self.ptr.as_ptr() as *mut u8;
84            unsafe { alloc::realloc(ptr, old_layout, new_layout.size()) }
85        };
86        if new_ptr.is_null() {
87            return Err(ResizeError::AllocationError(new_layout))
88        }
89
90        self.cap = new_cap;
91        self.ptr = unsafe { NonNull::new_unchecked(new_ptr as *mut T) };
92
93        Ok(())
94    }
95    pub fn try_expand_if_needed(&mut self, len: usize, n: usize) -> Result<(), ResizeError> {
96        if len == self.cap {
97            let mut new_cap = self.cap;
98            while new_cap - len < n {
99                new_cap = next_cap(new_cap);
100            }
101            self.resize_buffer(new_cap)?;
102        }
103        Ok(())
104    }
105    #[inline]
106    pub fn try_expand_if_needed_exact(&mut self, len: usize, n: usize) -> Result<(), ResizeError> {
107        if len == self.cap {
108            self.resize_buffer(n)?;
109        }
110        Ok(())
111    }
112
113    pub fn shrink_to_fit(&mut self, len: usize) {
114        self.resize_buffer(len).unwrap_or_else(|err| err.handle());
115    }
116    pub unsafe fn destroy(&mut self) {
117        if self.cap != 0 && mem::size_of::<T>() != 0 {
118            let layout = Layout::array::<T>(self.cap).unwrap();
119            unsafe {
120                let ptr = self.ptr.as_ptr() as *mut u8;
121                alloc::dealloc(ptr, layout);
122            }
123        }
124    }
125}
126
127#[cfg(not(feature = "alloc"))]
128#[allow(unused)]
129impl<T: Sized> RawVec<T> {
130    pub fn try_with_capacity(cap: usize) -> Result<Self,ResizeError> {
131        panic!("Alloc is not enabled. Can't switch the buffer to the heap")
132    }
133    fn resize_buffer(&mut self, new_cap: usize) {
134        panic!("Alloc is not enabled. Can't switch the buffer to the heap")
135    }
136
137    pub fn try_expand_if_needed(&mut self, len: usize, n: usize) -> Result<(), ResizeError> {
138        Err(ResizeError::AllocNotSupported)
139    }
140    #[inline]
141    pub fn try_expand_if_needed_exact(&mut self, len: usize, n: usize) -> Result<(), ResizeError> {
142        Err(ResizeError::AllocNotSupported)
143    }
144
145    pub fn shrink_to_fit(&mut self, len: usize) {
146        panic!("Alloc is not enabled. Can't switch the buffer to the heap")
147    }
148    pub unsafe fn destroy(&mut self) {
149        panic!("Alloc is not enabled. Can't switch the buffer to the heap")
150    }
151}
152
153impl<T: Sized> Clone for RawVec<T> {
154    fn clone(&self) -> Self {
155        *self
156    }
157}
158
159impl<T: Sized> Copy for RawVec<T> { }
160
161impl<T> Default for RawVec<T> {
162    fn default() -> Self {
163        Self::new()
164    }
165}