Implement array sizes in the 16-bit index range
This commit is contained in:
+29
-6
@@ -4,6 +4,9 @@ pub unsafe trait Array {
|
|||||||
/// The array's element type
|
/// The array's element type
|
||||||
type Item;
|
type Item;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
/// The smallest index type that indexes the array.
|
||||||
|
type Index: Index;
|
||||||
|
#[doc(hidden)]
|
||||||
fn as_ptr(&self) -> *const Self::Item;
|
fn as_ptr(&self) -> *const Self::Item;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn as_mut_ptr(&mut self) -> *mut Self::Item;
|
fn as_mut_ptr(&mut self) -> *mut Self::Item;
|
||||||
@@ -11,10 +14,29 @@ pub unsafe trait Array {
|
|||||||
fn capacity() -> usize;
|
fn capacity() -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Index : PartialEq + Copy {
|
||||||
|
fn zero() -> Self;
|
||||||
|
fn to_usize(self) -> usize;
|
||||||
|
fn from(usize) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index for u8 {
|
||||||
|
fn zero() -> Self { 0 }
|
||||||
|
fn to_usize(self) -> usize { self as usize }
|
||||||
|
fn from(ix: usize) -> Self { ix as u8 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index for u16 {
|
||||||
|
fn zero() -> Self { 0 }
|
||||||
|
fn to_usize(self) -> usize { self as usize }
|
||||||
|
fn from(ix: usize) -> Self { ix as u16 }
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! fix_array_impl {
|
macro_rules! fix_array_impl {
|
||||||
($len:expr ) => (
|
($index_type:ty, $len:expr ) => (
|
||||||
unsafe impl<T> Array for [T; $len] {
|
unsafe impl<T> Array for [T; $len] {
|
||||||
type Item = T;
|
type Item = T;
|
||||||
|
type Index = $index_type;
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
|
fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -26,14 +48,15 @@ macro_rules! fix_array_impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! fix_array_impl_recursive {
|
macro_rules! fix_array_impl_recursive {
|
||||||
() => ();
|
($index_type:ty, ) => ();
|
||||||
($len:expr, $($more:expr,)*) => (
|
($index_type:ty, $len:expr, $($more:expr,)*) => (
|
||||||
fix_array_impl!($len);
|
fix_array_impl!($index_type, $len);
|
||||||
fix_array_impl_recursive!($($more,)*);
|
fix_array_impl_recursive!($index_type, $($more,)*);
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fix_array_impl_recursive!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
fix_array_impl_recursive!(u8, 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,
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||||
32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,);
|
32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,);
|
||||||
|
fix_array_impl_recursive!(u16, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 32768,);
|
||||||
|
|
||||||
|
|||||||
+30
-17
@@ -20,6 +20,7 @@ mod array;
|
|||||||
mod misc;
|
mod misc;
|
||||||
pub use array::Array;
|
pub use array::Array;
|
||||||
pub use misc::RangeArgument;
|
pub use misc::RangeArgument;
|
||||||
|
use array::Index;
|
||||||
|
|
||||||
|
|
||||||
unsafe fn new_array<A: Array>() -> A {
|
unsafe fn new_array<A: Array>() -> A {
|
||||||
@@ -44,7 +45,7 @@ unsafe fn new_array<A: Array>() -> A {
|
|||||||
/// ArrayVec can be converted into a by value iterator.
|
/// ArrayVec can be converted into a by value iterator.
|
||||||
pub struct ArrayVec<A: Array> {
|
pub struct ArrayVec<A: Array> {
|
||||||
xs: NoDrop<A>,
|
xs: NoDrop<A>,
|
||||||
len: u8,
|
len: A::Index,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Array> Drop for ArrayVec<A> {
|
impl<A: Array> Drop for ArrayVec<A> {
|
||||||
@@ -72,7 +73,7 @@ impl<A: Array> ArrayVec<A> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn new() -> ArrayVec<A> {
|
pub fn new() -> ArrayVec<A> {
|
||||||
unsafe {
|
unsafe {
|
||||||
ArrayVec { xs: NoDrop::new(new_array()), len: 0 }
|
ArrayVec { xs: NoDrop::new(new_array()), len: Index::zero() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +88,7 @@ impl<A: Array> ArrayVec<A> {
|
|||||||
/// assert_eq!(array.len(), 2);
|
/// assert_eq!(array.len(), 2);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> usize { self.len as usize }
|
pub fn len(&self) -> usize { self.len.to_usize() }
|
||||||
|
|
||||||
/// Return the capacity of the **ArrayVec**.
|
/// Return the capacity of the **ArrayVec**.
|
||||||
///
|
///
|
||||||
@@ -122,11 +123,11 @@ impl<A: Array> ArrayVec<A> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn push(&mut self, element: A::Item) -> Option<A::Item> {
|
pub fn push(&mut self, element: A::Item) -> Option<A::Item> {
|
||||||
if self.len() < A::capacity() {
|
if self.len() < A::capacity() {
|
||||||
unsafe {
|
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
|
unsafe {
|
||||||
ptr::write(self.get_unchecked_mut(len), element);
|
ptr::write(self.get_unchecked_mut(len), element);
|
||||||
}
|
}
|
||||||
self.len += 1;
|
self.len = Index::from(len + 1);
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(element)
|
Some(element)
|
||||||
@@ -149,11 +150,11 @@ impl<A: Array> ArrayVec<A> {
|
|||||||
/// assert_eq!(array.pop(), None);
|
/// assert_eq!(array.pop(), None);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn pop(&mut self) -> Option<A::Item> {
|
pub fn pop(&mut self) -> Option<A::Item> {
|
||||||
if self.len == 0 {
|
if self.len() == 0 {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
self.len -= 1;
|
self.len = Index::from(self.len() - 1);
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
Some(ptr::read(self.get_unchecked_mut(len)))
|
Some(ptr::read(self.get_unchecked_mut(len)))
|
||||||
}
|
}
|
||||||
@@ -249,7 +250,7 @@ impl<A: Array> ArrayVec<A> {
|
|||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// set self.vec length's to start, to be safe in case Drain is leaked
|
// set self.vec length's to start, to be safe in case Drain is leaked
|
||||||
self.len = start as u8;
|
self.len = Index::from(start);
|
||||||
Drain {
|
Drain {
|
||||||
tail_start: end,
|
tail_start: end,
|
||||||
tail_len: len - end,
|
tail_len: len - end,
|
||||||
@@ -292,7 +293,7 @@ impl<A: Array> DerefMut for ArrayVec<A> {
|
|||||||
/// ```
|
/// ```
|
||||||
impl<A: Array> From<A> for ArrayVec<A> {
|
impl<A: Array> From<A> for ArrayVec<A> {
|
||||||
fn from(array: A) -> Self {
|
fn from(array: A) -> Self {
|
||||||
ArrayVec { xs: NoDrop::new(array), len: A::capacity() as u8 }
|
ArrayVec { xs: NoDrop::new(array), len: Index::from(A::capacity()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,14 +353,14 @@ impl<A: Array> IntoIterator for ArrayVec<A> {
|
|||||||
type Item = A::Item;
|
type Item = A::Item;
|
||||||
type IntoIter = IntoIter<A>;
|
type IntoIter = IntoIter<A>;
|
||||||
fn into_iter(self) -> IntoIter<A> {
|
fn into_iter(self) -> IntoIter<A> {
|
||||||
IntoIter { index: 0, v: self, }
|
IntoIter { index: Index::zero(), v: self, }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// By-value iterator for **ArrayVec**.
|
/// By-value iterator for **ArrayVec**.
|
||||||
pub struct IntoIter<A: Array> {
|
pub struct IntoIter<A: Array> {
|
||||||
index: u8,
|
index: A::Index,
|
||||||
v: ArrayVec<A>,
|
v: ArrayVec<A>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,16 +373,17 @@ impl<A: Array> Iterator for IntoIter<A> {
|
|||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = self.v.get_unchecked_mut(self.index as usize);
|
let index = self.index.to_usize();
|
||||||
|
let ptr = self.v.get_unchecked_mut(index);
|
||||||
let elt = ptr::read(ptr);
|
let elt = ptr::read(ptr);
|
||||||
self.index += 1;
|
self.index = Index::from(index + 1);
|
||||||
Some(elt)
|
Some(elt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
let len = self.v.len() - self.index as usize;
|
let len = self.v.len() - self.index.to_usize();
|
||||||
(len, Some(len))
|
(len, Some(len))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,7 +395,7 @@ impl<A: Array> DoubleEndedIterator for IntoIter<A> {
|
|||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.v.len -= 1;
|
self.v.len = Index::from(self.v.len() - 1);
|
||||||
let len = self.v.len();
|
let len = self.v.len();
|
||||||
let elt = ptr::read(self.v.get_unchecked_mut(len));
|
let elt = ptr::read(self.v.get_unchecked_mut(len));
|
||||||
Some(elt)
|
Some(elt)
|
||||||
@@ -408,7 +410,7 @@ impl<A: Array> Drop for IntoIter<A> {
|
|||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// exhaust iterator and clear the vector
|
// exhaust iterator and clear the vector
|
||||||
while let Some(_) = self.next() { }
|
while let Some(_) = self.next() { }
|
||||||
self.v.len = 0;
|
self.v.len = Index::zero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,7 +482,7 @@ impl<'a, A: Array> Drop for Drain<'a, A>
|
|||||||
let src = source_vec.as_ptr().offset(tail as isize);
|
let src = source_vec.as_ptr().offset(tail as isize);
|
||||||
let dst = source_vec.as_mut_ptr().offset(start as isize);
|
let dst = source_vec.as_mut_ptr().offset(start as isize);
|
||||||
ptr::copy(src, dst, self.tail_len);
|
ptr::copy(src, dst, self.tail_len);
|
||||||
source_vec.len = (start + self.tail_len) as u8;
|
source_vec.len = Index::from(start + self.tail_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -582,6 +584,17 @@ fn test_simple() {
|
|||||||
assert_eq!(sum_len, 8);
|
assert_eq!(sum_len, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_u16_index() {
|
||||||
|
const N: usize = 4096;
|
||||||
|
let mut vec: ArrayVec<[_; N]> = ArrayVec::new();
|
||||||
|
for _ in 0..N {
|
||||||
|
assert!(vec.push(1u8).is_none());
|
||||||
|
}
|
||||||
|
assert!(vec.push(0).is_some());
|
||||||
|
assert_eq!(vec.len(), N);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iter() {
|
fn test_iter() {
|
||||||
let mut iter = ArrayVec::from([1, 2, 3]).into_iter();
|
let mut iter = ArrayVec::from([1, 2, 3]).into_iter();
|
||||||
|
|||||||
Reference in New Issue
Block a user