#![allow(unused_variables)]
#![allow(unused_imports)]
+use std::fmt::{self, Debug};
+use std::marker::PhantomData;
use std::mem;
use std::mem::MaybeUninit;
+use std::ops::Deref;
pub fn default<T: Default>() -> T { Default::default() }
-#[derive(Debug)]
-struct AutoStackVec<const N: usize, T> {
+pub struct AutoStackVec<T, B> {
used: usize,
- buf: [T; N],
+ ph: PhantomData<T>,
+ buf: B,
}
-impl<const N: usize, T> AutoStackVec<N,T> {
- fn new() -> Self where T: Default {
+impl<T,B> Deref for AutoStackVec<T, B> where B: Buffer<T> {
+ type Target = [T];
+ fn deref(&self) -> &[T] {
+ unsafe {
+ std::slice::from_raw_parts(
+ self.buf.raw_ptr() as _,
+ self.used,
+ )
+ }
+ }
+}
+
+impl<T,B> Debug for AutoStackVec<T, B> where B: Buffer<T>, T: Debug {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ <[T] as Debug>::fmt(&*self, f)
+ }
+}
+
+#[repr(C)]
+pub struct Buf1<T, B> {
+ earlier: B,
+ item: MaybeUninit<T>,
+}
+
+pub unsafe trait Buffer<T> {
+ fn len() -> usize;
+ fn raw_ptr(&self) -> *const MaybeUninit<T> { self as *const _ as _ }
+ fn raw_mut(&mut self) -> *mut MaybeUninit<T> { self as *mut _ as _ }
+}
+unsafe impl<T> Buffer<T> for () {
+ fn len() -> usize { 0 }
+}
+unsafe impl<T,B> Buffer<T> for Buf1<T, B> where B: Buffer<T> {
+ fn len() -> usize { B::len() + 1 }
+}
+
+impl<T> AutoStackVec<T, ()> {
+ pub fn new() -> Self {
AutoStackVec {
used: 0,
- buf: std::array::from_fn(|_| default()),
+ ph: PhantomData,
+ buf: (),
+ }
+ }
+}
+
+impl<T,B> AutoStackVec<T, B> where B: Buffer<T> {
+ pub fn push_none(mut self) -> AutoStackVec<T, Buf1<T, B>> {
+ let mut out = AutoStackVec {
+ used: 0,
+ ph: self.ph,
+ buf: Buf1 {
+ earlier: self.buf,
+ item: MaybeUninit::uninit(),
+ },
+ };
+ out.used = self.used;
+ self.used = 0;
+ out
+ }
+
+ pub fn push(self, item: T) -> AutoStackVec<T, Buf1<T, B>> {
+ unsafe {
+ let mut out = self.push_none();
+ let item = MaybeUninit::new(item);
+ (out.buf.raw_mut())
+ .add(out.used)
+ .write(item);
+ out.used += 1;
+ out
+ }
+ }
+
+ pub fn push_option(self, item: Option<T>) -> AutoStackVec<T, Buf1<T, B>> {
+ if let Some(item) = item {
+ self.push(item)
+ } else {
+ self.push_none()
}
}
}
fn main(){
- let asv = AutoStackVec::<4, i32>::new();
+ let asv = AutoStackVec::<i32,_>::new();
+ let asv = asv.push(42);
eprintln!("N {:?}", asv);
}