// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A stack-allocated vector, allowing storage of N elements on the stack. use std::marker::Unsize; use std::iter::Extend; use std::ptr::{self, drop_in_place}; use std::ops::{Deref, DerefMut, Range}; use std::hash::{Hash, Hasher}; use std::slice; use std::fmt; use std::mem; pub unsafe trait Array { type Element; type PartialStorage: Default + Unsize<[ManuallyDrop]>; const LEN: usize; } unsafe impl Array for [T; 1] { type Element = T; type PartialStorage = [ManuallyDrop; 1]; const LEN: usize = 1; } unsafe impl Array for [T; 8] { type Element = T; type PartialStorage = [ManuallyDrop; 8]; const LEN: usize = 8; } pub struct ArrayVec { count: usize, values: A::PartialStorage } impl Hash for ArrayVec where A: Array, A::Element: Hash { fn hash(&self, state: &mut H) where H: Hasher { (&self[..]).hash(state); } } impl PartialEq for ArrayVec { fn eq(&self, other: &Self) -> bool { self == other } } impl Eq for ArrayVec {} impl Clone for ArrayVec where A: Array, A::Element: Clone { fn clone(&self) -> Self { let mut v = ArrayVec::new(); v.extend(self.iter().cloned()); v } } impl ArrayVec { pub fn new() -> Self { ArrayVec { count: 0, values: Default::default(), } } pub fn len(&self) -> usize { self.count } pub unsafe fn set_len(&mut self, len: usize) { self.count = len; } /// Panics when the stack vector is full. pub fn push(&mut self, el: A::Element) { let arr = &mut self.values as &mut [ManuallyDrop<_>]; arr[self.count] = ManuallyDrop { value: el }; self.count += 1; } pub fn pop(&mut self) -> Option { if self.count > 0 { let arr = &mut self.values as &mut [ManuallyDrop<_>]; self.count -= 1; unsafe { let value = ptr::read(&arr[self.count]); Some(value.value) } } else { None } } } impl Default for ArrayVec where A: Array { fn default() -> Self { ArrayVec::new() } } impl fmt::Debug for ArrayVec where A: Array, A::Element: fmt::Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self[..].fmt(f) } } impl Deref for ArrayVec { type Target = [A::Element]; fn deref(&self) -> &Self::Target { unsafe { slice::from_raw_parts(&self.values as *const _ as *const A::Element, self.count) } } } impl DerefMut for ArrayVec { fn deref_mut(&mut self) -> &mut [A::Element] { unsafe { slice::from_raw_parts_mut(&mut self.values as *mut _ as *mut A::Element, self.count) } } } impl Drop for ArrayVec { fn drop(&mut self) { unsafe { drop_in_place(&mut self[..]) } } } impl Extend for ArrayVec { fn extend(&mut self, iter: I) where I: IntoIterator { for el in iter { self.push(el); } } } pub struct Iter { indices: Range, store: A::PartialStorage, } impl Drop for Iter { fn drop(&mut self) { for _ in self {} } } impl Iterator for Iter { type Item = A::Element; fn next(&mut self) -> Option { let arr = &self.store as &[ManuallyDrop<_>]; unsafe { self.indices.next().map(|i| ptr::read(&arr[i]).value) } } fn size_hint(&self) -> (usize, Option) { self.indices.size_hint() } } impl IntoIterator for ArrayVec { type Item = A::Element; type IntoIter = Iter; fn into_iter(self) -> Self::IntoIter { let store = unsafe { ptr::read(&self.values) }; let indices = 0..self.count; mem::forget(self); Iter { indices: indices, store: store, } } } impl<'a, A: Array> IntoIterator for &'a ArrayVec { type Item = &'a A::Element; type IntoIter = slice::Iter<'a, A::Element>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a, A: Array> IntoIterator for &'a mut ArrayVec { type Item = &'a mut A::Element; type IntoIter = slice::IterMut<'a, A::Element>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } // FIXME: This should use repr(transparent) from rust-lang/rfcs#1758. #[allow(unions_with_drop_fields)] pub union ManuallyDrop { value: T, #[allow(dead_code)] empty: (), } impl ManuallyDrop { fn new() -> ManuallyDrop { ManuallyDrop { empty: () } } } impl Default for ManuallyDrop { fn default() -> Self { ManuallyDrop::new() } }