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}