use std::marker::PhantomData;
use std::os::raw::{c_char, c_uint, c_void};
use std::sync::Arc;
use std::{mem, ops, ptr, slice};
use sys;
pub struct Blob<'a> {
raw: *mut sys::hb_blob_t,
phantom: PhantomData<&'a [u8]>,
}
impl<'a> Blob<'a> {
pub fn new_read_only(data: &'a [u8]) -> Blob<'a> {
assert!(data.len() <= c_uint::max_value() as usize);
unsafe {
Blob::from_raw(sys::hb_blob_create(
data.as_ptr() as *const c_char,
data.len() as c_uint,
sys::HB_MEMORY_MODE_READONLY,
ptr::null_mut(), None, ))
}
}
pub fn new_from_arc_vec(data: Arc<Vec<u8>>) -> Blob<'static> {
let len = data.len();
assert!(len <= c_uint::max_value() as usize);
unsafe {
let data_ptr = data.as_ptr();
let ptr = Arc::into_raw(data);
unsafe extern "C" fn arc_vec_blob_destroy(user_data: *mut c_void) {
drop(Arc::from_raw(user_data as *const Vec<u8>))
}
let hb_blob = sys::hb_blob_create(
data_ptr as *const c_char,
len as c_uint,
sys::HB_MEMORY_MODE_READONLY,
ptr as *mut c_void,
Some(arc_vec_blob_destroy),
);
Blob::from_raw(hb_blob)
}
}
pub unsafe fn from_raw(raw: *mut sys::hb_blob_t) -> Self {
Blob {
raw,
phantom: PhantomData,
}
}
pub fn len(&self) -> usize {
unsafe { sys::hb_blob_get_length(self.raw) as usize }
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn make_immutable(&mut self) {
unsafe { sys::hb_blob_make_immutable(self.raw); }
}
pub fn is_immutable(&self) -> bool {
unsafe { sys::hb_blob_is_immutable(self.raw) != 0 }
}
pub fn as_raw(&self) -> *mut sys::hb_blob_t {
self.raw
}
pub fn into_raw(self) -> *mut sys::hb_blob_t {
let raw = self.raw;
mem::forget(self);
raw
}
}
impl<'a> ops::Deref for Blob<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
let mut len = 0;
let ptr = sys::hb_blob_get_data(self.raw, &mut len);
assert!(!ptr.is_null(), "hb_blob_get_data failed");
slice::from_raw_parts(ptr as *const u8, len as usize)
}
}
}
impl<'a> ops::DerefMut for Blob<'a> {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
let mut len = 0;
let ptr = sys::hb_blob_get_data_writable(self.raw, &mut len);
assert!(!ptr.is_null(), "hb_blob_get_data_writable failed");
slice::from_raw_parts_mut(ptr as *mut u8, len as usize)
}
}
}
impl<'a> Drop for Blob<'a> {
fn drop(&mut self) {
unsafe { sys::hb_blob_destroy(self.raw); }
}
}