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