use crate::{Error, Result};
use std::ffi::c_void;
use std::ops::Deref;
use std::ptr::NonNull;
#[derive(Debug)]
pub struct VipsOwnedBuffer {
ptr: Option<NonNull<u8>>,
len: usize,
}
unsafe impl Send for VipsOwnedBuffer {}
unsafe impl Sync for VipsOwnedBuffer {}
impl VipsOwnedBuffer {
pub(crate) unsafe fn from_raw(ptr: *mut c_void, len: usize) -> Result<Self> {
let buffer = Self {
ptr: NonNull::new(ptr.cast()),
len,
};
if len > isize::MAX as usize || (len != 0 && buffer.ptr.is_none()) {
return Err(Error::Other(
"invalid libvips output buffer length or pointer".into(),
));
}
Ok(buffer)
}
pub fn as_slice(&self) -> &[u8] {
if self.len == 0 {
return &[];
}
unsafe { std::slice::from_raw_parts(self.ptr.unwrap().as_ptr(), self.len) }
}
}
impl Deref for VipsOwnedBuffer {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.as_slice()
}
}
impl AsRef<[u8]> for VipsOwnedBuffer {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl Drop for VipsOwnedBuffer {
fn drop(&mut self) {
if let Some(ptr) = self.ptr {
unsafe { vips_sys::g_free(ptr.as_ptr().cast()) };
}
}
}