Initial commit
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "arrayvec"
|
||||
version = "0.1.0"
|
||||
authors = ["bluss"]
|
||||
|
||||
[features]
|
||||
|
||||
unstable = []
|
||||
+280
@@ -0,0 +1,280 @@
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::ops::{
|
||||
Deref,
|
||||
DerefMut,
|
||||
};
|
||||
use std::slice;
|
||||
use std::convert::From;
|
||||
|
||||
|
||||
/// Make sure the non-nullable pointer optimization does not occur!
|
||||
enum Flag<T> {
|
||||
Alive(T),
|
||||
Dropped,
|
||||
_Unused,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Dud(i32);
|
||||
|
||||
impl Drop for Dud {
|
||||
fn drop(&mut self) {
|
||||
let Dud(ref i) = *self;
|
||||
println!("Drop Dud({})", *i);
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for fixed size arrays.
|
||||
pub unsafe trait Array {
|
||||
type Item;
|
||||
unsafe fn new() -> Self;
|
||||
fn as_ptr(&self) -> *const Self::Item;
|
||||
fn as_mut_ptr(&mut self) -> *mut Self::Item;
|
||||
fn capacity() -> usize;
|
||||
}
|
||||
|
||||
macro_rules! fix_array_impl {
|
||||
($len:expr ) => (
|
||||
unsafe impl<T> Array for [T; $len] {
|
||||
type Item = T;
|
||||
unsafe fn new() -> [T; $len] { mem::uninitialized() }
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
|
||||
fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _}
|
||||
#[inline]
|
||||
fn capacity() -> usize { $len }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! fix_array_impl_recursive {
|
||||
() => ();
|
||||
($len:expr, $($more:expr,)*) => (
|
||||
fix_array_impl!($len);
|
||||
fix_array_impl_recursive!($($more,)*);
|
||||
);
|
||||
}
|
||||
|
||||
fix_array_impl_recursive!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 48, 64, 96, 128,);
|
||||
|
||||
/// A vector with a fixed capacity.
|
||||
///
|
||||
/// The **ArrayVec** is backed by a fixed size array and keeps track of
|
||||
/// the number of initialized elements.
|
||||
///
|
||||
/// The ArrayVec is a congiguous value that you can store directly on the stack
|
||||
/// if needed.
|
||||
pub struct ArrayVec<A: Array> {
|
||||
len: u8,
|
||||
xs: Flag<A>,
|
||||
}
|
||||
|
||||
impl<A: Array> Drop for ArrayVec<A> {
|
||||
fn drop(&mut self) {
|
||||
// clear all elements, then inhibit drop of inner array
|
||||
while let Some(_) = self.pop() { }
|
||||
unsafe {
|
||||
ptr::write(&mut self.xs, Flag::Dropped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> ArrayVec<A> {
|
||||
pub fn new() -> ArrayVec<A> {
|
||||
unsafe {
|
||||
ArrayVec { xs: Flag::Alive(Array::new()), len: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from(array: A) -> ArrayVec<A> {
|
||||
ArrayVec { xs: Flag::Alive(array), len: A::capacity() as u8 }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn capacity(&self) -> usize { A::capacity() }
|
||||
|
||||
#[inline]
|
||||
fn array(&self) -> &A {
|
||||
match self.xs {
|
||||
Flag::Alive(ref xs) => xs,
|
||||
_ => unreachable!(),
|
||||
//_ => std::intrinsics::unreachable(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn array_mut(&mut self) -> &mut A {
|
||||
// FIXME: Optimize this, we know it's always Some.
|
||||
match self.xs {
|
||||
Flag::Alive(ref mut xs) => xs,
|
||||
_ => unreachable!(),
|
||||
//_ => std::intrinsics::unreachable(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize { self.len as usize }
|
||||
|
||||
pub fn push(&mut self, elt: A::Item) -> Option<A::Item> {
|
||||
if self.len() < A::capacity() {
|
||||
unsafe {
|
||||
let len = self.len();
|
||||
ptr::write(self.get_unchecked_mut(len), elt);
|
||||
}
|
||||
self.len += 1;
|
||||
None
|
||||
} else {
|
||||
Some(elt)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<A::Item> {
|
||||
if self.len == 0 {
|
||||
return None
|
||||
}
|
||||
unsafe {
|
||||
self.len -= 1;
|
||||
let len = self.len();
|
||||
Some(ptr::read(self.get_unchecked_mut(len)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> Deref for ArrayVec<A> {
|
||||
type Target = [A::Item];
|
||||
#[inline]
|
||||
fn deref(&self) -> &[A::Item] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.array().as_ptr(), self.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> DerefMut for ArrayVec<A> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut [A::Item] {
|
||||
let len = self.len();
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(self.array_mut().as_mut_ptr(), len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A: Array> IntoIterator for &'a ArrayVec<A> {
|
||||
type Item = &'a A::Item;
|
||||
type IntoIter = slice::Iter<'a, A::Item>;
|
||||
fn into_iter(self) -> Self::IntoIter { self.iter() }
|
||||
}
|
||||
|
||||
impl<A: Array> IntoIterator for ArrayVec<A> {
|
||||
type Item = A::Item;
|
||||
type IntoIter = IntoIter<A>;
|
||||
fn into_iter(self) -> IntoIter<A> {
|
||||
IntoIter { index: 0, v: self, }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// By-value iterator for ArrayVec.
|
||||
pub struct IntoIter<A: Array> {
|
||||
index: u8,
|
||||
v: ArrayVec<A>,
|
||||
}
|
||||
|
||||
impl<A: Array> Iterator for IntoIter<A> {
|
||||
type Item = A::Item;
|
||||
|
||||
fn next(&mut self) -> Option<A::Item> {
|
||||
if self.index == self.v.len {
|
||||
None
|
||||
} else {
|
||||
unsafe {
|
||||
let ptr = self.v.get_unchecked_mut(self.index as usize);
|
||||
let elt = ptr::read(ptr);
|
||||
self.index += 1;
|
||||
Some(elt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> Drop for IntoIter<A> {
|
||||
fn drop(&mut self) {
|
||||
// exhaust iterator and clear the vector
|
||||
while let Some(_) = self.next() { }
|
||||
self.v.len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test1() {
|
||||
let mut vec: ArrayVec<[Vec<i32>; 3]> = ArrayVec::new();
|
||||
|
||||
vec.push(vec![1,2,4,5]);
|
||||
vec.push(vec![3]);
|
||||
vec.push(vec![97,98,92]);
|
||||
|
||||
for elt in vec {
|
||||
println!("{:?}", elt);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut v = ArrayVec::from([1, 2, 3]);
|
||||
v.push(4);
|
||||
v.push(5);
|
||||
println!("{:?}", v.pop());
|
||||
println!("{:?}", v.pop());
|
||||
println!("{:?}", &*v);
|
||||
v.pop();
|
||||
v.pop();
|
||||
v.push(8);
|
||||
println!("{:?}", &*v);
|
||||
|
||||
let mut u: ArrayVec<[_; 3]> = ArrayVec::new();
|
||||
|
||||
u.push(vec![1,2,4,5]);
|
||||
u.push(vec![3]);
|
||||
u.push(vec![97,98,92]);
|
||||
|
||||
{
|
||||
let slc: &[_] = &u;
|
||||
println!("{:?}", slc);
|
||||
}
|
||||
println!("{:?}", u.pop());
|
||||
println!("{:?}", u.pop());
|
||||
println!("{:?}", u.len());
|
||||
println!("{:?}", u[0]);
|
||||
|
||||
|
||||
let mut v: ArrayVec<[Dud; 2]> = ArrayVec::new();
|
||||
v.push(Dud(1));
|
||||
v.push(Dud(2));
|
||||
v.pop();
|
||||
v.pop();
|
||||
v.pop();
|
||||
v.push(Dud(3));
|
||||
v.pop();
|
||||
v.push(Dud(4));
|
||||
v.push(Dud(5));
|
||||
v.push(Dud(6));
|
||||
//v.pop();
|
||||
|
||||
println!("v: {:?}", &*v);
|
||||
|
||||
for elt in &v { // slice iter
|
||||
println!("Slice Iter: {:?}", elt);
|
||||
}
|
||||
|
||||
for elt in v {
|
||||
println!("Iter: {:?}", elt);
|
||||
//break;
|
||||
}
|
||||
|
||||
for elt in ArrayVec::from(["a".to_string(), "b".to_string()]).into_iter() {
|
||||
println!("Iter: {:?}", elt);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user