elastic_array/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![cfg_attr(not(feature = "std"), feature(alloc))]
3
4#[cfg(not(feature = "std"))]
5#[macro_use]
6extern crate alloc;
7
8#[cfg(feature="heapsizeof")]
9extern crate heapsize;
10
11#[cfg(feature = "std")] use std::cmp::Ordering;
12#[cfg(feature = "std")] use std::hash::{Hash, Hasher};
13#[cfg(feature = "std")] use std::fmt;
14#[cfg(feature = "std")] use std::ops::Deref;
15
16#[cfg(not(feature = "std"))] use core::cmp::Ordering;
17#[cfg(not(feature = "std"))] use core::hash::{Hash, Hasher};
18#[cfg(not(feature = "std"))] use core::fmt;
19#[cfg(not(feature = "std"))] use core::ops::Deref;
20
21#[cfg(feature="heapsizeof")]
22use heapsize::HeapSizeOf;
23
24#[cfg(not(feature = "std"))]
25use alloc::vec::Vec;
26
27#[macro_export]
28macro_rules! impl_elastic_array {
29	($name: ident, $dummy: ident, $size: expr) => (
30		#[doc(hidden)]
31		enum $dummy<T> {
32			Arr([T; $size]),
33			Vec(Vec<T>)
34		}
35
36		impl<T> $dummy<T> {
37			#[doc(hidden)]
38			pub fn slice(&self) -> &[T] {
39				match *self {
40					$dummy::Arr(ref v) => v,
41					$dummy::Vec(ref v) => v
42				}
43			}
44		}
45
46		impl<T> Clone for $dummy<T> where T: Copy {
47			fn clone(&self) -> $dummy<T> {
48				match *self {
49					$dummy::Arr(ref a) => $dummy::Arr(*a),
50					$dummy::Vec(ref v) => $dummy::Vec(v.clone()),
51				}
52			}
53		}
54
55		pub struct $name<T> {
56			raw: $dummy<T>,
57			len: usize
58		}
59
60		impl<T> Eq for $name<T> where T: Eq { }
61
62		impl<T> fmt::Debug for $name<T> where T: fmt::Debug {
63			fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
64				match self.raw {
65					$dummy::Arr(ref a) => (&a[..self.len]).fmt(f),
66					$dummy::Vec(ref v) => v.fmt(f),
67				}
68			}
69		}
70
71		impl<T, U> PartialEq<U> for $name<T> where T: PartialEq, U: Deref<Target=[T]> {
72			fn eq(&self, other: &U) -> bool {
73				self.slice() == &**other
74			}
75		}
76
77		impl<T, U> PartialOrd<U> for $name<T> where T: PartialOrd, U: Deref<Target=[T]> {
78			fn partial_cmp(&self, other: &U) -> Option<Ordering> {
79				(&**self).partial_cmp(&*other)
80			}
81		}
82
83		impl<T> Ord for $name<T> where T: Ord {
84			fn cmp(&self, other: &Self) -> Ordering {
85				(&**self).cmp(&*other)
86			}
87		} 
88
89		impl<T> Hash for $name<T> where T: Hash {
90			fn hash<H>(&self, state: &mut H) where H: Hasher {
91				self.slice().hash(state)
92			}
93		}
94
95        #[cfg(feature="heapsizeof")]
96		impl<T> HeapSizeOf for $name<T> where T: HeapSizeOf {
97			fn heap_size_of_children(&self) -> usize {
98				match self.raw {
99					$dummy::Arr(_) => 0,
100					$dummy::Vec(ref v) => v.heap_size_of_children()
101				}
102			}
103		}
104
105		impl<T> Clone for $name<T> where T: Copy {
106			fn clone(&self) -> $name<T> {
107				$name {
108					raw: self.raw.clone(),
109					len: self.len,
110				}
111			}
112		}
113
114		impl<T> Default for $name<T> where T: Copy {
115			fn default() -> $name<T> {
116				Self::new()
117			}
118		}
119
120		impl<T> $name<T> where T: Copy {
121			pub fn new() -> $name<T> {
122                #[cfg(feature = "std")]
123				use std::mem;
124
125                #[cfg(not(feature = "std"))]
126				use core::mem;
127
128				$name {
129					raw: $dummy::Arr(unsafe { mem::uninitialized() }),
130					len: 0
131				}
132			}
133
134			pub fn from_slice(slice: &[T]) -> $name<T> {
135				let mut v = $name::new();
136				v.append_slice(slice);
137				v
138			}
139
140			pub fn from_vec(vec: Vec<T>) -> $name<T> {
141				$name {
142					len: vec.len(),
143					raw: $dummy::Vec(vec),
144				}
145			}
146
147			pub fn push(&mut self, e: T) {
148                #[cfg(feature = "std")]
149				use std::ptr;
150
151                #[cfg(not(feature = "std"))]
152				use core::ptr;
153
154				match self.raw {
155					$dummy::Arr(ref mut a) if self.len < a.len() => {
156						unsafe {
157							*a.get_unchecked_mut(self.len) = e;
158						}
159					},
160					$dummy::Arr(_) => {
161						let mut vec = vec![];
162						vec.reserve(self.len + 1);
163
164						unsafe {
165							ptr::copy(self.raw.slice().as_ptr(), vec.as_mut_ptr(), self.len);
166							vec.set_len(self.len);
167						}
168
169						vec.push(e);
170						self.raw = $dummy::Vec(vec);
171					},
172					$dummy::Vec(ref mut v) => v.push(e)
173				}
174				self.len += 1;
175			}
176
177			pub fn pop(&mut self) -> Option<T> {
178				if self.len == 0 {
179					return None;
180				}
181
182				self.len -= 1;
183				match self.raw {
184					$dummy::Arr(ref a) => Some(a[self.len]),
185					$dummy::Vec(ref mut v) => v.pop()
186				}
187			}
188
189			pub fn clear(&mut self) {
190                #[cfg(feature = "std")]
191				use std::mem;
192
193                #[cfg(not(feature = "std"))]
194				use core::mem;
195
196				self.raw = $dummy::Arr(unsafe {mem::uninitialized() });
197				self.len = 0;
198			}
199
200			pub fn append_slice(&mut self, elements: &[T]) {
201				let len = self.len;
202				self.insert_slice(len, elements)
203			}
204
205			pub fn into_vec(self) -> Vec<T> {
206                #[cfg(feature = "std")]
207				use std::ptr;
208
209                #[cfg(not(feature = "std"))]
210				use core::ptr;
211
212				match self.raw {
213					$dummy::Arr(a) => {
214						let mut vec = vec![];
215						vec.reserve(self.len);
216						unsafe {
217							ptr::copy(a.as_ptr(), vec.as_mut_ptr(), self.len);
218							vec.set_len(self.len);
219						}
220						vec
221					}
222					$dummy::Vec(v) => v
223				}
224			}
225
226			pub fn insert_slice(&mut self, index: usize, elements: &[T]) {
227                #[cfg(feature = "std")]
228				use std::ptr;
229
230                #[cfg(not(feature = "std"))]
231				use core::ptr;
232
233				let elen = elements.len();
234
235				if elen == 0 {
236					return;
237				}
238				
239				let len = self.len;
240				assert!(index <= len);
241
242				match self.raw {
243					// it fits in array
244					$dummy::Arr(ref mut a) if len + elen <= a.len() => unsafe {
245						let p = a.as_mut_ptr().offset(index as isize);
246						let ep = elements.as_ptr();
247
248						// shift everything by elen, to make space
249						ptr::copy(p, p.offset(elen as isize), len - index);
250						// write new elements
251						ptr::copy(ep, p, elen);
252					},
253					// it deosn't, must be rewritten to vec
254					$dummy::Arr(_) => unsafe {
255						let mut vec = vec![];
256						vec.reserve(self.len + elen);
257						{
258							let p = vec.as_mut_ptr();
259							let ob = self.raw.slice().as_ptr();
260							let ep = elements.as_ptr();
261							let oe = ob.offset(index as isize);
262							
263							// copy begining of an array
264							ptr::copy(ob, p, index);
265
266							// copy new elements
267							ptr::copy(ep, p.offset(index as isize), elen);
268
269							// copy end of an array	
270							ptr::copy(oe, p.offset((index + elen) as isize), len - index);
271						}
272						vec.set_len(self.len + elen);
273						self.raw = $dummy::Vec(vec);
274					},
275					// just insert it in to vec
276					$dummy::Vec(ref mut v) => unsafe {
277						v.reserve(elen);
278
279						let p = v.as_mut_ptr().offset(index as isize);
280						let ep = elements.as_ptr();
281
282						// shift everything by elen, to make space
283						ptr::copy(p, p.offset(elen as isize), len - index);
284						// write new elements
285						ptr::copy(ep, p, elen);
286
287						v.set_len(self.len + elen);
288					}
289				}
290				self.len += elen;
291			}
292		}
293
294		impl<T> $name<T> {
295			fn slice(&self) -> &[T] {
296				match self.raw {
297					$dummy::Arr(ref a) => &a[..self.len],
298					$dummy::Vec(ref v) => v
299				}
300			}
301		}
302
303		impl<T> Deref for $name<T> {
304			type Target = [T];
305
306			#[inline]
307			fn deref(&self) -> &[T] {
308				self.slice()
309			}
310		}
311
312        #[cfg(not(feature = "std"))]
313		impl<T> ::core::convert::AsRef<[T]> for $name<T> {
314			#[inline]
315			fn as_ref(&self) -> &[T] {
316				self.slice()
317			}
318		}
319
320        #[cfg(feature = "std")]
321		impl<T> ::std::convert::AsRef<[T]> for $name<T> {
322			#[inline]
323			fn as_ref(&self) -> &[T] {
324				self.slice()
325			}
326		}
327
328        #[cfg(not(feature = "std"))]
329		impl<T> ::core::borrow::Borrow<[T]> for $name<T> {
330			#[inline]
331			fn borrow(&self) -> &[T] {
332				self.slice()
333			}
334		}
335
336        #[cfg(feature = "std")]
337		impl<T> ::std::borrow::Borrow<[T]> for $name<T> {
338			#[inline]
339			fn borrow(&self) -> &[T] {
340				self.slice()
341			}
342		}
343
344        #[cfg(not(feature = "std"))]
345        impl<T> ::core::ops::DerefMut for $name<T> {
346			#[inline]
347			fn deref_mut(&mut self) -> &mut [T] {
348				match self.raw {
349					$dummy::Arr(ref mut a) => &mut a[..self.len],
350					$dummy::Vec(ref mut v) => v
351				}
352			}
353		}
354
355        #[cfg(feature = "std")]
356		impl<T> ::std::ops::DerefMut for $name<T> {
357			#[inline]
358			fn deref_mut(&mut self) -> &mut [T] {
359				match self.raw {
360					$dummy::Arr(ref mut a) => &mut a[..self.len],
361					$dummy::Vec(ref mut v) => v
362				}
363			}
364		}
365
366		impl<'a, T: 'a + Copy> From<&'a [T]> for $name<T> {
367			fn from(s: &'a [T]) -> Self { Self::from_slice(s) }
368		}
369	)
370}
371
372impl_elastic_array!(ElasticArray2, ElasticArray2Dummy, 2);
373impl_elastic_array!(ElasticArray4, ElasticArray4Dummy, 4);
374impl_elastic_array!(ElasticArray8, ElasticArray8Dummy, 8);
375impl_elastic_array!(ElasticArray16, ElasticArray16Dummy, 16);
376impl_elastic_array!(ElasticArray32, ElasticArray32Dummy, 32);
377impl_elastic_array!(ElasticArray36, ElasticArray36Dummy, 36);
378impl_elastic_array!(ElasticArray64, ElasticArray64Dummy, 64);
379impl_elastic_array!(ElasticArray128, ElasticArray128Dummy, 128);
380impl_elastic_array!(ElasticArray256, ElasticArray256Dummy, 256);
381impl_elastic_array!(ElasticArray512, ElasticArray512Dummy, 512);
382impl_elastic_array!(ElasticArray1024, ElasticArray1024Dummy, 1024);
383impl_elastic_array!(ElasticArray2048, ElasticArray2048Dummy, 2048);
384
385#[cfg(test)]
386mod tests {
387
388	type BytesShort = super::ElasticArray2<u8>;
389
390	#[test]
391	fn it_works() {
392		let mut bytes = BytesShort::new();
393		assert_eq!(bytes.len(), 0);
394		bytes.push(1);
395		assert_eq!(bytes.len(), 1);
396		assert_eq!(bytes[0], 1);
397		bytes.push(2);
398		assert_eq!(bytes[1], 2);
399		assert_eq!(bytes.len(), 2);
400		bytes.push(3);
401		assert_eq!(bytes[2], 3);
402		assert_eq!(bytes.len(), 3);
403		assert_eq!(bytes.pop(), Some(3));
404		assert_eq!(bytes.len(), 2);
405		assert_eq!(bytes.pop(), Some(2));
406		assert_eq!(bytes.pop(), Some(1));
407		assert_eq!(bytes.pop(), None);
408	}
409
410	#[test]
411	fn test_insert_slice() {
412		let mut bytes = BytesShort::new();
413		bytes.push(1);
414		bytes.push(2);
415		bytes.insert_slice(1, &[3, 4]);
416		assert_eq!(bytes.len(), 4);
417		let r: &[u8] = &bytes;
418		assert_eq!(r, &[1, 3, 4, 2]);
419	}
420
421	#[test]
422	fn append_slice() {
423		let mut bytes = BytesShort::new();
424		bytes.push(1);
425		bytes.append_slice(&[3, 4]);
426		let r: &[u8] = &bytes;
427		assert_eq!(r.len(), 3);
428		assert_eq!(r, &[1, 3 ,4]);
429	}
430
431	#[test]
432	fn use_in_map() {
433		use std::collections::HashMap;
434		use std::borrow::Borrow;
435		let mut map: HashMap<BytesShort, i32> = HashMap::new();
436		let mut bytes = BytesShort::new();
437		bytes.append_slice(&[3, 4]);
438		assert_eq!(bytes.borrow() as &[u8], &[3, 4][..]);
439		map.insert(bytes, 1);
440		assert_eq!(map.get(&[3, 4][..]), Some(&1i32));
441	}
442}
443
444