Skip to content

Instantly share code, notes, and snippets.

@orlp

orlp/vararray.rs Secret

Created October 20, 2018 21:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save orlp/2c0a704c3a30f6203fcaa33aca941f1c to your computer and use it in GitHub Desktop.
Save orlp/2c0a704c3a30f6203fcaa33aca941f1c to your computer and use it in GitHub Desktop.
use std::mem::ManuallyDrop;
#[derive(Clone, Copy)]
pub enum VarArray<T> {
L0([T; 0]), L1([T; 1]), L2([T; 2]), L3([T; 3]),
L4([T; 4]), L5([T; 5]), L6([T; 6]), L7([T; 7]),
L8([T; 8]),
}
// Convert regular array to VarArray<T>.
macro_rules! vararray_from {
( $(($i:ident, $n:expr)),+ ) => {
$(
impl<T> From<[T; $n]> for VarArray<T> {
fn from(a: [T; $n]) -> Self { VarArray::$i(a) }
}
)+
}
}
vararray_from!((L0, 0), (L1, 1), (L2, 2), (L3, 3),
(L4, 4), (L5, 5), (L6, 6), (L7, 7),
(L8, 8));
impl<T> VarArray<T> {
pub unsafe fn get_unchecked_mut(&mut self, n: usize) -> &mut T {
match self {
VarArray::L0(a) => a.get_unchecked_mut(n),
VarArray::L1(a) => a.get_unchecked_mut(n),
VarArray::L2(a) => a.get_unchecked_mut(n),
VarArray::L3(a) => a.get_unchecked_mut(n),
VarArray::L4(a) => a.get_unchecked_mut(n),
VarArray::L5(a) => a.get_unchecked_mut(n),
VarArray::L6(a) => a.get_unchecked_mut(n),
VarArray::L7(a) => a.get_unchecked_mut(n),
VarArray::L8(a) => a.get_unchecked_mut(n),
}
}
}
#[derive(Clone)]
struct ArrayIntoIter<T> {
data: ManuallyDrop<VarArray<T>>,
len: usize,
cur: usize,
}
impl<T> Iterator for ArrayIntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.cur >= self.len {
return None;
}
let idx = self.cur;
self.cur += 1;
Some(unsafe { std::ptr::read(self.data.get_unchecked_mut(idx)) })
}
}
impl<T> Drop for ArrayIntoIter<T> {
fn drop(&mut self) {
unsafe {
let elems = std::slice::from_raw_parts_mut(
self.data.get_unchecked_mut(self.cur) as *mut T,
self.len - self.cur
);
self.len = 0;
self.cur = 0;
std::ptr::drop_in_place(elems);
}
}
}
trait IntoIterator {
type Item;
type IntoIter: Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter;
}
macro_rules! array_intoiter {
($($n:expr),+) => { $(
impl<T> IntoIterator for [T; $n] {
type Item = T;
type IntoIter = ArrayIntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
let len = self.len();
ArrayIntoIter {
data: ManuallyDrop::new(VarArray::from(self)),
len,
cur: 0,
}
}
}
)+ }
}
array_intoiter!(0, 1, 2, 3, 4, 5, 6, 7, 8);
fn main() {
let a = [1, 2, 3, 4];
let v: Vec<i32> = a.into_iter().collect();
println!("{:?}", v);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment