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