use super::super::resources::ResourceToken;

pub struct FixedBufGuard {
    token: Option<ResourceToken>,
    buf_index: u16,
    ptr: *mut u8,
    cap: usize,
}

impl FixedBufGuard {
    pub(in crate::driver) fn new(
        token: ResourceToken,
        buf_index: u16,
        ptr: *mut u8,
        cap: usize,
    ) -> Self {
        Self {
            token: Some(token),
            buf_index,
            ptr,
            cap,
        }
    }

    pub fn fixed_write(&self, src: &[u8]) -> FixedBufWrite {
        let len = src.len().min(self.cap);
        if len != 0 {
            unsafe {
                std::ptr::copy_nonoverlapping(src.as_ptr(), self.ptr, len);
            }
        }
        FixedBufWrite::new(self.ptr as *const u8, len as u32, self.buf_index)
    }
}

impl Drop for FixedBufGuard {
    fn drop(&mut self) {
        if let Some(token) = self.token.take() {
            token.release();
        }
    }
}

#[derive(Clone, Copy, Debug)]
pub struct FixedBufWrite {
    ptr: *const u8,
    len: u32,
    buf_index: u16,
}

impl FixedBufWrite {
    #[must_use]
    pub(crate) const fn new(ptr: *const u8, len: u32, buf_index: u16) -> Self {
        Self {
            ptr,
            len,
            buf_index,
        }
    }

    pub const fn ptr(self) -> *const u8 {
        self.ptr
    }

    pub const fn len(self) -> u32 {
        self.len
    }

    pub const fn index(self) -> u16 {
        self.buf_index
    }
}
