io2 0.0.2

single threaded async-io library
Documentation
use std::{
    alloc::{AllocError, Allocator, Layout},
    ptr::NonNull,
};

pub struct IoBuffer<A: Allocator> {
    alloc: A,
    ptr: NonNull<u8>,
    layout: Layout,
    size: usize,
}

impl<A: Allocator> IoBuffer<A> {
    pub fn new(layout: Layout, alloc: A) -> Result<Self, AllocError> {
        let mut slice = alloc.allocate_zeroed(layout)?;
        let ptr = unsafe { NonNull::new_unchecked(slice.as_mut().as_mut_ptr()) };
        let size = layout.size();
        let layout = Layout::from_size_align(slice.len(), layout.align()).unwrap();
        Ok(Self {
            alloc,
            ptr,
            layout,
            size,
        })
    }

    pub fn as_slice(&self) -> &[u8] {
        unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.size) }
    }

    pub fn as_mut_slice(&mut self) -> &mut [u8] {
        unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.size) }
    }

    pub fn view(self, offset: usize, len: usize) -> IoBufferView<A> {
        IoBufferView::new(self, offset, len)
    }

    pub fn size(&self) -> usize {
        self.size
    }
}

impl<A: Allocator> Drop for IoBuffer<A> {
    fn drop(&mut self) {
        unsafe {
            self.alloc.deallocate(self.ptr, self.layout);
        }
    }
}

pub struct IoBufferView<A: Allocator> {
    buf: IoBuffer<A>,
    offset: usize,
    len: usize,
}

impl<A: Allocator> IoBufferView<A> {
    pub fn new(buf: IoBuffer<A>, offset: usize, len: usize) -> Self {
        assert!(buf.layout.size() >= offset + len);
        Self { buf, offset, len }
    }

    pub fn as_slice(&self) -> &[u8] {
        assert!(self.buf.layout.size() >= self.offset + self.len);
        unsafe { std::slice::from_raw_parts(self.buf.ptr.add(self.offset).as_ptr(), self.len) }
    }

    pub fn len(&self) -> usize {
        self.len
    }

    pub fn is_empty(&self) -> bool {
        self.len > 0
    }
}