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 $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 ptr::copy(p, p.offset(elen as isize), len - index);
250 ptr::copy(ep, p, elen);
252 },
253 $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 ptr::copy(ob, p, index);
265
266 ptr::copy(ep, p.offset(index as isize), elen);
268
269 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 $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 ptr::copy(p, p.offset(elen as isize), len - index);
284 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