static_collections/vec.rs
1// The static-vector module
2
3use core::{mem::MaybeUninit, ops::{Deref, DerefMut}, ptr, slice};
4
5#[derive(Debug)]
6pub struct StaticVec<const N:usize,T:Sized>
7{
8 length:usize,
9 buff:MaybeUninit<[T;N]>
10}
11
12impl<const N:usize,T:Sized> Default for StaticVec<N,T>
13{
14 fn default() -> Self
15 {
16 Self::new()
17 }
18}
19
20impl<const N:usize,T:Sized> StaticVec<N,T>
21{
22 /// Constructs a new, empty StaticVec<N,T>.
23 ///
24 /// The `new` method will not zero the buffer, so the initial operation is very inexpensive.
25 ///
26 /// # Example
27 /// ```
28 /// use static_collections::vec::StaticVec;
29 /// let mut v:StaticVec<8,u64>=StaticVec::new();
30 /// ```
31 pub const fn new()->Self
32 {
33 Self
34 {
35 length:0,
36 buff:MaybeUninit::uninit()
37 }
38 }
39
40 pub const fn as_slice(&self)->&[T]
41 {
42 unsafe
43 {
44 slice::from_raw_parts(self.as_ptr(),self.length)
45 }
46 }
47
48 pub const fn as_mut_slice(&mut self)->&mut [T]
49 {
50 unsafe
51 {
52 slice::from_raw_parts_mut(self.as_mut_ptr(),self.length)
53 }
54 }
55
56 pub const fn as_ptr(&self)->*const T
57 {
58 unsafe
59 {
60 self.buff.assume_init_ref().as_ptr()
61 }
62 }
63
64 pub const fn as_mut_ptr(&mut self)->*mut T
65 {
66 unsafe
67 {
68 self.buff.assume_init_mut().as_mut_ptr()
69 }
70 }
71
72 /// Put value `v` to the end of static vector.
73 ///
74 /// # Example
75 /// ```
76 /// use static_collections::vec::StaticVec;
77 /// let mut v:StaticVec<8,u64>=StaticVec::new();
78 /// v.push(1234);
79 /// assert_eq!(v.as_slice(),&[1234]);
80 /// v.push(4567);
81 /// assert_eq!(v.as_slice(),&[1234,4567]);
82 /// ```
83 pub fn push(&mut self,v:T)
84 {
85 if self.length<N
86 {
87 unsafe
88 {
89 self.buff.assume_init_mut()[self.length]=v;
90 }
91 self.length+=1;
92 }
93 }
94
95 /// Read and remove the value at the end of the static vector.
96 ///
97 /// # Example
98 /// ```
99 /// use static_collections::vec::StaticVec;
100 /// let mut v:StaticVec<8,u64>=StaticVec::new();
101 /// v.push(1234);
102 /// assert_eq!(v.pop(),1234);
103 /// ```
104 pub fn pop(&mut self)->T
105 {
106 if self.length>0
107 {
108 self.length-=1;
109 // Use unsafe codes to avoid `Copy` trait.
110 unsafe
111 {
112 ptr::read(self.as_ptr().add(self.length))
113 }
114 }
115 else
116 {
117 panic!("popping a value from an empty static vector!");
118 }
119 }
120
121 /// Insert value `v` to a specific location of static vector.
122 ///
123 /// # Example
124 /// ```
125 /// use static_collections::vec::StaticVec;
126 /// let mut v:StaticVec<8,u64>=StaticVec::new();
127 /// v.push(1234);
128 /// v.push(4567);
129 /// v.insert(1,2333);
130 /// assert_eq!(v.as_slice(),&[1234,2333,4567]);
131 /// ```
132 pub fn insert(&mut self,index:usize,v:T)
133 {
134 if self.length<N && index<=self.length
135 {
136 // Use unsafe codes to avoid `Copy` trait.
137 unsafe
138 {
139 let p=self.as_mut_ptr().add(index);
140 ptr::copy(p,p.add(1),self.length-index);
141 ptr::write(p,v);
142 }
143 self.length+=1;
144 }
145 }
146
147 /// Read and remove the value at location `index` of the static vector.
148 ///
149 /// # Example
150 /// ```
151 /// use static_collections::vec::StaticVec;
152 /// let mut v:StaticVec<8,u64>=StaticVec::new();
153 /// v.push(1234);
154 /// v.push(4567);
155 /// v.push(7890);
156 /// assert_eq!(v.remove(1),4567);
157 /// assert_eq!(v.as_slice(),&[1234,7890]);
158 /// ```
159 pub fn remove(&mut self,index:usize)->T
160 {
161 if self.length>index
162 {
163 // Use unsafe codes to avoid `Copy` trait.
164 unsafe
165 {
166 let p=self.as_mut_ptr().add(index);
167 let v=ptr::read(self.as_ptr().add(index));
168 ptr::copy(p.add(1),p,self.length-index-1);
169 self.length-=1;
170 v
171 }
172 }
173 else
174 {
175 panic!("removal index ({index}) is out of bound ({})!",self.length);
176 }
177 }
178
179 /// Shortens this static-vector to the specified `new_len`.
180 ///
181 /// # Examples
182 /// ```
183 /// use static_collections::vec::StaticVec;
184 /// let mut v:StaticVec<8,u64>=StaticVec::new();
185 /// v.push(0);
186 /// v.push(1);
187 /// v.push(2);
188 /// v.push(3);
189 /// v.push(4);
190 /// v.push(5);
191 /// v.truncate(2);
192 /// assert_eq!(v.as_slice(),&[0,1]);
193 /// ```
194 pub fn truncate(&mut self,new_len:usize)
195 {
196 if new_len<self.length
197 {
198 self.length=new_len;
199 }
200 }
201
202 /// Removes all values from the static-vector.
203 ///
204 /// # Example
205 /// ```
206 /// use static_collections::vec::StaticVec;
207 /// let mut v:StaticVec<8,u64>=StaticVec::new();
208 /// v.push(12345);
209 /// v.push(67890);
210 /// v.clear();
211 /// assert_eq!(v.as_slice(),&[]);
212 /// ```
213 pub fn clear(&mut self)
214 {
215 self.length=0;
216 }
217
218 /// Checks if the static-vector is empty.
219 ///
220 /// # Example
221 /// ```
222 /// use static_collections::vec::StaticVec;
223 /// let mut v:StaticVec<8,u64>=StaticVec::new();
224 /// v.push(12);
225 /// v.push(34);
226 /// assert!(!v.is_empty());
227 /// v.clear();
228 /// assert!(v.is_empty());
229 /// ```
230 pub fn is_empty(&self)->bool
231 {
232 self.len()==0
233 }
234
235 /// Returns the number of values in the static-vector.
236 ///
237 /// # Example
238 /// ```
239 /// use static_collections::vec::StaticVec;
240 /// let mut v:StaticVec<8,u64>=StaticVec::new();
241 /// assert_eq!(v.len(),0);
242 /// v.push(1);
243 /// assert_eq!(v.len(),1);
244 /// ```
245 pub const fn len(&self)->usize
246 {
247 self.length
248 }
249
250 /// Returns the capacity of the static-vector.
251 ///
252 /// # Example
253 /// ```
254 /// use static_collections::vec::StaticVec;
255 /// let v:StaticVec<12,u64>=StaticVec::new();
256 /// assert_eq!(v.capacity(),12);
257 /// ```
258 pub const fn capacity(&self)->usize
259 {
260 N
261 }
262
263 /// This routine is a helper routine that constructs a static-vector for the `vec_static!` macro. \
264 /// This routine assigns the `value` specified at location `index` in the static-vector.
265 ///
266 /// # Safety
267 /// Do not use this routine on your own. This routine is only supposed to be called by `vec_static!` macro, \
268 /// and the `index` is allowed to go beyond the `self.len()` limit. That's why this routine is unsafe.
269 ///
270 /// # Panic
271 /// If `index>=N`, internal assertion would fail.
272 pub const unsafe fn force_assign(&mut self,index:usize,value:T)
273 {
274 assert!(index<N);
275 unsafe
276 {
277 ptr::write(self.buff.assume_init_mut().as_mut_ptr().add(index),value);
278 }
279 }
280
281 /// This routine is a helper routine that constructs a static-vector for the `vec_static!` macro. \
282 /// This routine resizes the static vector with specified length.
283 ///
284 /// # Safety
285 /// Do not use this routine on your own. This routine is only supposed to be called by `vec_static!` macro. \
286 /// If `index>self.length`, the static-vector may end with undefined contents.
287 ///
288 /// # Panic
289 /// If `length>N`, internal assertion would fail.
290 pub const unsafe fn force_resize(&mut self,length:usize)
291 {
292 assert!(length<=N);
293 self.length=length;
294 }
295}
296
297impl<const N:usize,T> Deref for StaticVec<N,T>
298{
299 type Target = [T];
300
301 fn deref(&self) -> &Self::Target
302 {
303 self.as_slice()
304 }
305}
306
307impl<const N:usize,T> DerefMut for StaticVec<N,T>
308{
309 fn deref_mut(&mut self) -> &mut Self::Target
310 {
311 self.as_mut_slice()
312 }
313}
314
315/// The `vec_static!` macro helps building a static-vector easily,
316/// similar to the `vec!` macro in `std`/`alloc` crate.
317///
318/// # Example
319/// ```
320/// use static_collections::{vec_static,vec::StaticVec};
321/// let a:StaticVec<12,u64>=vec_static![4;7];
322/// assert_eq!(a.as_slice(),&[4;7]);
323/// let b:StaticVec<16,u32>=vec_static![1,2,3,4,5,6,7,8];
324/// assert_eq!(b.as_slice(),&[1,2,3,4,5,6,7,8]);
325/// ```
326#[macro_export] macro_rules! vec_static
327{
328 ()=>
329 (
330 $crate::vec::StaticVec::new()
331 );
332 ($elem:expr;$len:expr)=>
333 (
334 {
335 let mut v=StaticVec::new();
336 unsafe
337 {
338 let mut i:usize=0;
339 while i<$len
340 {
341 v.force_assign(i,$elem);
342 i+=1;
343 }
344 v.force_resize($len);
345 }
346 v
347 }
348 );
349 ($($x:expr),+$(,)?)=>
350 (
351 {
352 let mut v=StaticVec::new();
353 let mut index:usize=0;
354 unsafe
355 {
356 $(
357 {
358 v.force_assign(index,$x);
359 index+=1;
360 }
361 )*
362 v.force_resize(index);
363 }
364 v
365 }
366 );
367}
368
369#[cfg(test)] mod test
370{
371 extern crate std;
372
373 use std::println;
374 use crate::vec::StaticVec;
375
376 #[should_panic]
377 #[test] fn vec_macro_overflow()
378 {
379 let x:StaticVec<12,u64>=vec_static![1234;16];
380 println!("{x:?}")
381 }
382}