Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use core::marker::{PhantomPinned, Unpin};
- use core::mem::MaybeUninit;
- use core::pin::Pin;
- extern crate alloc;
- use alloc::alloc as ma;
- #[repr(C)]
- pub struct PinSmallVecData<A>
- where
- A: Array + Unpin,
- A::Item: Unpin,
- {
- ptr: *mut A::Item,
- len: usize,
- cap: usize,
- inline_items: MaybeUninit<A>,
- _boo: PhantomPinned,
- }
- impl<A> PinSmallVecData<A>
- where
- A: Array + Unpin,
- A::Item: Unpin,
- {
- pub fn new() -> Self {
- Self {
- ptr: core::ptr::null_mut(),
- len: 0,
- cap: 0,
- inline_items: MaybeUninit::uninit(),
- _boo: PhantomPinned,
- }
- }
- }
- pub struct PinSmallVec<'a, A>
- where
- A: Array + Unpin,
- A::Item: Unpin,
- {
- data: Pin<&'a mut PinSmallVecData<A>>,
- }
- impl<'a, A> PinSmallVec<'a, A>
- where
- A: Array + Unpin,
- A::Item: Unpin,
- {
- #[doc(hidden)]
- pub unsafe fn new(v: &'a mut PinSmallVecData<A>) -> Self {
- v.ptr = v.inline_items.as_mut_ptr() as *mut _;
- v.cap = A::size();
- v.len = 0;
- Self {
- data: Pin::new_unchecked(v),
- }
- }
- #[inline]
- pub fn len(&self) -> usize {
- self.data.len
- }
- #[inline]
- pub fn capacity(&self) -> usize {
- self.data.cap
- }
- #[inline]
- pub fn is_small(&self) -> bool {
- (self.data.ptr as usize) == (self.data.inline_items.as_ptr() as usize)
- }
- #[inline]
- pub fn as_slice(&self) -> &[A::Item] {
- unsafe { core::slice::from_raw_parts(self.data.ptr, self.data.len) }
- }
- #[inline]
- pub fn as_slice_mut(&mut self) -> &mut [A::Item] {
- unsafe { core::slice::from_raw_parts_mut(self.data.ptr, self.data.len) }
- }
- #[inline]
- pub fn push(&mut self, v: A::Item) {
- if self.capacity() == self.len() {
- self.grow(self.capacity() + 1);
- }
- // debug_assert!(self.capacity() > self.len());
- unsafe {
- let mut data = self.data.as_mut().get_unchecked_mut();
- data.ptr.add(data.len).write(v);
- data.len += 1;
- }
- }
- #[inline]
- pub fn pop(&mut self) -> Option<A::Item> {
- if self.len() == 0 {
- return None;
- }
- unsafe {
- let mut data = self.data.as_mut().get_unchecked_mut();
- data.len -= 1;
- let len = data.len;
- Some(data.ptr.add(len).read())
- }
- }
- #[cold]
- fn grow(&mut self, min_c: usize) {
- // note: this is not intended to be fully production ready.
- unsafe {
- let mut data = self.data.as_mut().get_unchecked_mut();
- let new_c = min_c.max(2 * data.cap + 1);
- let small = (data.ptr as usize) == (data.inline_items.as_ptr() as usize);
- if !small {
- let layout = ma::Layout::from_size_align(
- core::mem::size_of::<A::Item>() * data.cap,
- core::mem::align_of::<A::Item>(),
- ).unwrap();
- let np = ma::realloc(data.ptr as *mut u8, layout, new_c * core::mem::size_of::<A::Item>());
- if np.is_null() {
- ma::handle_alloc_error(layout);
- }
- data.ptr = np as *mut A::Item;
- data.cap = new_c;
- } else {
- let layout = ma::Layout::from_size_align(
- core::mem::size_of::<A::Item>() * new_c,
- core::mem::align_of::<A::Item>(),
- )
- .unwrap();
- let np = ma::alloc(layout);
- if np.is_null() {
- ma::handle_alloc_error(layout);
- }
- let np = np as *mut A::Item;
- core::ptr::copy_nonoverlapping(data.ptr, np, data.len);
- data.ptr = np;
- data.cap = new_c;
- }
- }
- }
- }
- impl<'a, A> Drop for PinSmallVec<'a, A>
- where
- A: Array + Unpin,
- A::Item: Unpin,
- {
- fn drop(&mut self) {
- while let Some(_) = self.pop() {};
- if !self.is_small() {
- let c = self.capacity();
- let layout = ma::Layout::from_size_align(
- core::mem::size_of::<A::Item>() * c,
- core::mem::align_of::<A::Item>(),
- ).unwrap();
- unsafe {
- ma::dealloc(self.data.ptr as *mut _, layout);
- }
- }
- }
- }
- macro_rules! local_smallvec {
- ($name:ident : [$T:ty; $N:expr]) => {
- let mut $name: PinSmallVecData<[$T; $N]> = PinSmallVecData::new();
- #[allow(unused_mut)]
- let mut $name: PinSmallVec<'_, [$T; $N]> = unsafe { PinSmallVec::new(&mut $name) };
- };
- }
- fn main() {
- local_smallvec!(foobars: [i32; 0x40]);
- for x in 0..100i32 {
- foobars.push(x);
- }
- for x in (0..100i32).rev() {
- assert_eq!(foobars.pop(), Some(x));
- }
- assert_eq!(foobars.pop(), None);
- }
- /// rest off this is from smallvec crate once the maybeuninit patch lands
- pub unsafe trait Array {
- type Item;
- fn size() -> usize;
- }
- macro_rules! impl_array {
- ($($N:expr),*) => {$(
- unsafe impl<T> Array for [T; $N] {
- #[inline] fn size() -> usize { $N }
- type Item = T;
- }
- )*}
- }
- impl_array!(
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800,
- 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000
- );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement