linear-deque 0.1.3

A double-ended queue that can be sliced at any time without preparation.
Documentation
extern crate alloc as alloc_crate;
use alloc_crate::alloc;

use alloc::Layout;
use core::mem;
use core::ptr::NonNull;

#[derive(Debug)]
pub struct Buffer<T> {
    pub ptr: NonNull<T>,
    pub cap: usize,
}

unsafe impl<T: Send> Send for Buffer<T> {}
unsafe impl<T: Sync> Sync for Buffer<T> {}

impl<T> Buffer<T> {
    pub fn new() -> Self {
        let cap = if mem::size_of::<T>() == 0 {
            usize::MAX
        } else {
            0
        };

        Buffer {
            ptr: NonNull::dangling(),
            cap,
        }
    }

    pub fn realloc(&mut self, new_cap: usize) {
        assert!(mem::size_of::<T>() != 0, "capacity overflow");
        assert!(new_cap > 0, "can't realloc to zero length");

        let new_layout = Layout::array::<T>(new_cap).unwrap();

        let new_ptr = if self.cap == 0 {
            unsafe { alloc::alloc(new_layout) }
        } else {
            let old_layout = Layout::array::<T>(self.cap).unwrap();
            let old_ptr = self.ptr.as_ptr().cast::<u8>();
            unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
        };

        self.ptr = match NonNull::new(new_ptr.cast::<T>()) {
            Some(p) => p,
            None => alloc::handle_alloc_error(new_layout),
        };
        self.cap = new_cap;
    }
}

impl<T> Drop for Buffer<T> {
    fn drop(&mut self) {
        let elem_size = mem::size_of::<T>();

        if self.cap != 0 && elem_size != 0 {
            unsafe {
                alloc::dealloc(
                    self.ptr.as_ptr().cast::<u8>(),
                    Layout::array::<T>(self.cap).unwrap(),
                );
            }
        }
    }
}