// 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. //! //! Currently, only the N = 8 case is supported (due to Array only being impl-ed for [T; 8]). use std::marker::Unsize; use std::iter::Extend; use std::ptr::drop_in_place; use std::ops::{Deref, DerefMut}; use std::slice; use std::fmt; pub unsafe trait Array { type Element; type PartialStorage: Default + Unsize<[ManuallyDrop]>; const LEN: usize; } 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 ArrayVec { pub fn new() -> Self { ArrayVec { count: 0, values: Default::default(), } } } 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 { unsafe { let arr = &mut self.values as &mut [ManuallyDrop<_>]; arr[self.count].value = el; } self.count += 1; } } } // 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 Default for ManuallyDrop { fn default() -> Self { ManuallyDrop { empty: () } } }