Skip to main content

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(),Some(1234));
117	/// ```
118	pub fn pop(&mut self)->Option<T>
119	{
120		if self.length>0
121		{
122			self.length-=1;
123			// Use unsafe codes to avoid `Copy` trait.
124			unsafe
125			{
126				Some(ptr::read(self.as_ptr().add(self.length)))
127			}
128		}
129		else
130		{
131			None
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	/// v.push(1234);
171	/// assert_eq!(v.remove(1),Some(4567));
172	/// assert_eq!(v.as_slice(),&[1234,7890,1234]);
173	/// ```
174	pub fn remove(&mut self,index:usize)->Option<T>
175	{
176		if self.length>index
177		{
178			// Use unsafe codes to avoid `Copy` and `Drop` trait.
179			unsafe
180			{
181				let p=self.as_mut_ptr().add(index);
182				let v=ptr::read(self.as_ptr().add(index));
183				ptr::copy(p.add(1),p,self.length-index-1);
184				self.length-=1;
185				Some(v)
186			}
187		}
188		else
189		{
190			None
191		}
192	}
193
194	/// Shortens this static-vector to the specified `new_len`.
195	/// 
196	/// # Examples
197	/// ```
198	/// use static_collections::vec::StaticVec;
199	/// let mut v:StaticVec<8,u64>=StaticVec::new();
200	/// v.push(0);
201	/// v.push(1);
202	/// v.push(2);
203	/// v.push(3);
204	/// v.push(4);
205	/// v.push(5);
206	/// v.truncate(2);
207	/// assert_eq!(v.as_slice(),&[0,1]);
208	/// ```
209	pub fn truncate(&mut self,new_len:usize)
210	{
211		if new_len<self.length
212		{
213			// Force drop every item.
214			for item in &mut self[new_len..]
215			{
216				drop(unsafe{ptr::read(item)});
217			}
218			self.length=new_len;
219		}
220	}
221
222	/// Removes all values from the static-vector.
223	/// 
224	/// # Example
225	/// ```
226	/// use static_collections::vec::StaticVec;
227	/// let mut v:StaticVec<8,u64>=StaticVec::new();
228	/// v.push(12345);
229	/// v.push(67890);
230	/// v.clear();
231	/// assert_eq!(v.as_slice(),&[]);
232	/// ```
233	pub fn clear(&mut self)
234	{
235		for item in self.as_mut_slice()
236		{
237			// Force drop every item.
238			drop(unsafe{ptr::read(item)});
239		}
240		self.length=0;
241	}
242
243	/// Checks if the static-vector is empty.
244	/// 
245	/// # Example
246	/// ```
247	/// use static_collections::vec::StaticVec;
248	/// let mut v:StaticVec<8,u64>=StaticVec::new();
249	/// v.push(12);
250	/// v.push(34);
251	/// assert!(!v.is_empty());
252	/// v.clear();
253	/// assert!(v.is_empty());
254	/// ```
255	pub fn is_empty(&self)->bool
256	{
257		self.len()==0
258	}
259
260	/// Returns the number of values in the static-vector.
261	/// 
262	/// # Example
263	/// ```
264	/// use static_collections::vec::StaticVec;
265	/// let mut v:StaticVec<8,u64>=StaticVec::new();
266	/// assert_eq!(v.len(),0);
267	/// v.push(1);
268	/// assert_eq!(v.len(),1);
269	/// ```
270	pub const fn len(&self)->usize
271	{
272		self.length
273	}
274
275	/// Returns the capacity of the static-vector.
276	/// 
277	/// # Example
278	/// ```
279	/// use static_collections::vec::StaticVec;
280	/// let v:StaticVec<12,u64>=StaticVec::new();
281	/// assert_eq!(v.capacity(),12);
282	/// ```
283	pub const fn capacity(&self)->usize
284	{
285		N
286	}
287
288	/// This routine is a helper routine that constructs a static-vector for the `vec_static!` macro. \
289	/// This routine assigns the `value` specified at location `index` in the static-vector.
290	/// 
291	/// # Safety
292	/// Do not use this routine on your own. This routine is only supposed to be called by `vec_static!` macro, \
293	/// and the `index` is allowed to go beyond the `self.len()` limit. That's why this routine is unsafe.
294	/// 
295	/// # Panic
296	/// If `index>=N`, internal assertion would fail.
297	pub const unsafe fn force_assign(&mut self,index:usize,value:T)
298	{
299		assert!(index<N);
300		unsafe
301		{
302			ptr::write(self.buff.assume_init_mut().as_mut_ptr().add(index),value);
303		}
304	}
305
306	/// This routine is a helper routine that constructs a static-vector for the `vec_static!` macro. \
307	/// This routine resizes the static vector with specified length. \
308	/// Should you wish to use `force_resize` method, read the `# Safety` and `# Panic` chapters.
309	/// 
310	/// # Safety
311	/// If `index>self.length`, the static-vector may end with undefined contents. \
312	/// You should get rid of these undefined contents after you force resized this vector.
313	/// 
314	/// # Panic
315	/// If `length>N`, internal assertion would fail.
316	pub const unsafe fn force_resize(&mut self,length:usize)
317	{
318		assert!(length<=N,"The new length exceeds capacity!");
319		self.length=length;
320	}
321}
322
323impl<const N:usize,T> Drop for StaticVec<N,T>
324{
325	fn drop(&mut self)
326	{
327		self.clear();
328	}
329}
330
331impl<const N:usize,T> Deref for StaticVec<N,T>
332{
333	type Target = [T];
334
335	fn deref(&self) -> &Self::Target
336	{
337		self.as_slice()
338	}
339}
340
341impl<const N:usize,T> DerefMut for StaticVec<N,T>
342{
343	fn deref_mut(&mut self) -> &mut Self::Target
344	{
345		self.as_mut_slice()
346	}
347}
348
349/// The `vec_static!` macro helps building a static-vector easily,
350/// similar to the `vec!` macro in `std`/`alloc` crate.
351/// 
352/// # Example
353/// ```
354/// use static_collections::{vec_static,vec::StaticVec};
355/// let a:StaticVec<12,u64>=vec_static![4;7];
356/// assert_eq!(a.as_slice(),&[4;7]);
357/// let b:StaticVec<16,u32>=vec_static![1,2,3,4,5,6,7,8];
358/// assert_eq!(b.as_slice(),&[1,2,3,4,5,6,7,8]);
359/// ```
360#[macro_export] macro_rules! vec_static
361{
362	()=>
363	(
364		$crate::vec::StaticVec::new()
365	);
366	($elem:expr;$len:expr)=>
367	(
368		{
369			let mut v=StaticVec::new();
370			unsafe
371			{
372				let mut i:usize=0;
373				while i<$len
374				{
375					v.force_assign(i,$elem);
376					i+=1;
377				}
378				v.force_resize($len);
379			}
380			v
381		}
382	);
383	($($x:expr),+$(,)?)=>
384	(
385		{
386			let mut v=StaticVec::new();
387			let mut index:usize=0;
388			unsafe
389			{
390				$(
391					{
392						v.force_assign(index,$x);
393						index+=1;
394					}
395				)*
396				v.force_resize(index);
397			}
398			v
399		}
400	);
401}
402
403#[cfg(test)] mod test
404{
405	extern crate std;
406
407	use std::println;
408	use crate::vec::StaticVec;
409
410	#[should_panic]
411	#[test] fn vec_macro_overflow()
412	{
413		let x:StaticVec<12,u64>=vec_static![1234;16];
414		println!("{x:?}")
415	}
416
417	#[test] fn clone()
418	{
419		let x:StaticVec<16,u64>=vec_static![1,2,3,4,5,6,7,8,9,10];
420		assert_eq!(x.len(),10);
421		let y=x.clone();
422		assert_eq!(*y,[1,2,3,4,5,6,7,8,9,10]);
423	}
424
425	#[test] fn drop()
426	{
427		use core::sync::atomic::{AtomicUsize,Ordering};
428
429		struct DropCounter<'a>
430		{
431			counter:&'a AtomicUsize
432		}
433
434		impl<'a> Drop for DropCounter<'a>
435		{
436			fn drop(&mut self)
437			{
438				self.counter.fetch_add(1,Ordering::SeqCst);
439			}
440		}
441
442		let drop_count:AtomicUsize=AtomicUsize::new(0);
443		{
444			let mut v:StaticVec<8,DropCounter>=StaticVec::new();
445			v.push(DropCounter{counter:&drop_count});
446			v.push(DropCounter{counter:&drop_count});
447			assert_eq!(drop_count.load(Ordering::SeqCst),0);
448			v.pop();
449			assert_eq!(drop_count.load(Ordering::SeqCst),1);
450			v.clear();
451			assert_eq!(drop_count.load(Ordering::SeqCst),2);
452			v.push(DropCounter{counter:&drop_count});
453			v.push(DropCounter{counter:&drop_count});
454			assert_eq!(drop_count.load(Ordering::SeqCst),2);
455			v.push(DropCounter{counter:&drop_count});
456			v.push(DropCounter{counter:&drop_count});
457			v.push(DropCounter{counter:&drop_count});
458			assert_eq!(drop_count.load(Ordering::SeqCst),2);
459			assert_eq!(v.len(),5);
460			v.truncate(3);
461			assert_eq!(drop_count.load(Ordering::SeqCst),4);
462		}
463		assert_eq!(drop_count.load(Ordering::SeqCst),7);
464	}
465}