use crate::driver::current_driver_mut;

pub struct ProvidedBuf {
    bid: u16,
    ptr: *mut u8,
    start: usize,
    len: usize,
    released: bool,
}

impl ProvidedBuf {
    pub(crate) fn new(bid: u16, ptr: *mut u8, cap: usize, len: usize) -> Self {
        assert!(
            len <= cap,
            "provided buffer length must not exceed guard capacity"
        );
        Self {
            bid,
            ptr,
            start: 0,
            len,
            released: false,
        }
    }

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

    pub fn as_slice(&self) -> &[u8] {
        let start_ptr = unsafe { self.ptr.add(self.start) };
        unsafe { std::slice::from_raw_parts(start_ptr as *const u8, self.len) }
    }

    #[allow(clippy::should_implement_trait)]
    pub fn as_mut(&mut self) -> &mut [u8] {
        let start_ptr = unsafe { self.ptr.add(self.start) };
        unsafe { std::slice::from_raw_parts_mut(start_ptr, self.len) }
    }
}

impl Drop for ProvidedBuf {
    fn drop(&mut self) {
        if self.released {
            return;
        }
        current_driver_mut().provided.release(self.bid);
    }
}

impl AsRef<[u8]> for ProvidedBuf {
    fn as_ref(&self) -> &[u8] {
        self.as_slice()
    }
}
