use std::{ptr, slice};
use std::convert::{AsRef, AsMut};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
#[derive(Debug)]
pub struct OwnedBuf {
ptr: *mut u8,
len: usize,
}
impl Deref for OwnedBuf {
type Target = [u8];
fn deref(&self) -> &[u8] { unsafe { deref(self.ptr, self.len) } }
}
impl DerefMut for OwnedBuf {
fn deref_mut(&mut self) -> &mut [u8] { unsafe { deref_mut(self.ptr, self.len) } }
}
impl AsRef<[u8]> for OwnedBuf {
fn as_ref(&self) -> &[u8] { self.deref() }
}
impl AsMut<[u8]> for OwnedBuf {
fn as_mut(&mut self) -> &mut [u8] { self.deref_mut() }
}
impl OwnedBuf {
pub fn new() -> OwnedBuf {
OwnedBuf { ptr: ptr::null_mut(), len: 0 }
}
pub fn allocate(len: usize) -> OwnedBuf {
let ptr = unsafe { raw::tj3Alloc(len as raw::size_t) };
assert!(!ptr.is_null(), "tj3Alloc() returned null");
OwnedBuf { ptr: ptr as *mut u8, len }
}
pub fn copy_from_slice(data: &[u8]) -> OwnedBuf {
let buf = Self::allocate(data.len());
unsafe { ptr::copy_nonoverlapping(data.as_ptr(), buf.ptr, data.len()) }
buf
}
pub fn len(&self) -> usize {
self.len
}
}
impl Drop for OwnedBuf {
fn drop(&mut self) {
unsafe { raw::tj3Free(self.ptr as *mut libc::c_void) };
}
}
#[derive(Debug)]
pub struct OutputBuf<'a> {
pub(crate) ptr: *mut u8,
pub(crate) len: usize,
pub(crate) is_owned: bool,
pub(crate) _phantom: PhantomData<&'a mut [u8]>,
}
impl<'a> Deref for OutputBuf<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] { unsafe { deref(self.ptr, self.len) } }
}
impl<'a> DerefMut for OutputBuf<'a> {
fn deref_mut(&mut self) -> &mut [u8] { unsafe { deref_mut(self.ptr, self.len) } }
}
impl<'a> AsRef<[u8]> for OutputBuf<'a> {
fn as_ref(&self) -> &[u8] { self.deref() }
}
impl<'a> AsMut<[u8]> for OutputBuf<'a> {
fn as_mut(&mut self) -> &mut [u8] { self.deref_mut() }
}
impl<'a> OutputBuf<'a> {
pub fn borrowed(slice: &'a mut [u8]) -> OutputBuf<'a> {
OutputBuf {
ptr: slice.as_mut_ptr(),
len: slice.len(),
is_owned: false,
_phantom: PhantomData,
}
}
pub fn owned(mut buf: OwnedBuf) -> OutputBuf<'a> {
let OwnedBuf { ptr, len } = buf;
buf.ptr = ptr::null_mut(); OutputBuf {
ptr,
len,
is_owned: true,
_phantom: PhantomData,
}
}
pub fn new_owned() -> OutputBuf<'a> {
Self::owned(OwnedBuf::new())
}
pub fn allocate_owned(cap: usize) -> OutputBuf<'a> {
Self::owned(OwnedBuf::allocate(cap))
}
pub fn len(&self) -> usize {
self.len
}
pub fn into_owned(mut self) -> OwnedBuf {
let OutputBuf { ptr, len, is_owned, .. } = self;
self.ptr = ptr::null_mut(); if is_owned {
OwnedBuf { ptr, len }
} else {
unsafe {
OwnedBuf::copy_from_slice(slice::from_raw_parts(ptr, len))
}
}
}
}
impl<'a> Drop for OutputBuf<'a> {
fn drop(&mut self) {
if self.is_owned {
unsafe { raw::tj3Free(self.ptr as *mut libc::c_void) };
}
}
}
impl<'a> From<&'a mut [u8]> for OutputBuf<'a> {
fn from(slice: &'a mut [u8]) -> OutputBuf<'a> {
OutputBuf::borrowed(slice)
}
}
impl From<OwnedBuf> for OutputBuf<'static> {
fn from(buf: OwnedBuf) -> OutputBuf<'static> {
OutputBuf::owned(buf)
}
}
unsafe fn deref<'a>(ptr: *const u8, len: usize) -> &'a [u8] {
if len != 0 {
debug_assert!(!ptr.is_null());
slice::from_raw_parts(ptr, len)
} else {
&[]
}
}
unsafe fn deref_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut [u8] {
if len != 0 {
debug_assert!(!ptr.is_null());
slice::from_raw_parts_mut(ptr, len)
} else {
&mut []
}
}