use std::marker::PhantomData;
use std::mem::{self, MaybeUninit};
use std::os::raw::c_void;
use std::slice;
use context::{Context, Lock};
use borrow::{Borrow, BorrowMut, Ref, RefMut, LoanError};
use borrow::internal::Pointer;
use handle::Managed;
use types::{Value, Object, build};
use types::internal::ValueInternal;
use result::JsResult;
use neon_runtime;
use neon_runtime::raw;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct JsBuffer(raw::Local);
impl JsBuffer {
pub fn new<'a, C: Context<'a>>(_: &mut C, size: u32) -> JsResult<'a, JsBuffer> {
build(|out| { unsafe { neon_runtime::buffer::new(out, size) } })
}
pub unsafe fn uninitialized<'a, C: Context<'a>>(_: &mut C, size: u32) -> JsResult<'a, JsBuffer> {
build(|out| { neon_runtime::buffer::uninitialized(out, size) })
}
}
impl Managed for JsBuffer {
fn to_raw(self) -> raw::Local { self.0 }
fn from_raw(h: raw::Local) -> Self { JsBuffer(h) }
}
impl ValueInternal for JsBuffer {
fn name() -> String { "Buffer".to_string() }
fn is_typeof<Other: Value>(other: Other) -> bool {
unsafe { neon_runtime::tag::is_buffer(other.to_raw()) }
}
}
impl Value for JsBuffer { }
impl Object for JsBuffer { }
#[repr(C)]
#[derive(Clone, Copy)]
pub struct JsArrayBuffer(raw::Local);
impl JsArrayBuffer {
pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> JsResult<'a, JsArrayBuffer> {
build(|out| { unsafe { neon_runtime::arraybuffer::new(out, mem::transmute(cx.env()), size) } })
}
}
impl Managed for JsArrayBuffer {
fn to_raw(self) -> raw::Local { self.0 }
fn from_raw(h: raw::Local) -> Self { JsArrayBuffer(h) }
}
impl ValueInternal for JsArrayBuffer {
fn name() -> String { "ArrayBuffer".to_string() }
fn is_typeof<Other: Value>(other: Other) -> bool {
unsafe { neon_runtime::tag::is_arraybuffer(other.to_raw()) }
}
}
impl Value for JsArrayBuffer { }
impl Object for JsArrayBuffer { }
#[derive(Clone, Copy)]
#[repr(C)]
pub struct BinaryData<'a> {
base: *mut c_void,
size: usize,
phantom: PhantomData<&'a ()>
}
unsafe impl<'a> Pointer for BinaryData<'a> {
unsafe fn as_ptr(&self) -> *const c_void {
self.base
}
unsafe fn as_mut(&mut self) -> *mut c_void {
self.base
}
}
pub trait BinaryViewType: Sized { }
impl BinaryViewType for u8 { }
impl BinaryViewType for i8 { }
impl BinaryViewType for u16 { }
impl BinaryViewType for i16 { }
impl BinaryViewType for u32 { }
impl BinaryViewType for i32 { }
impl BinaryViewType for u64 { }
impl BinaryViewType for i64 { }
impl BinaryViewType for f32 { }
impl BinaryViewType for f64 { }
impl<'a> BinaryData<'a> {
pub fn as_slice<T: BinaryViewType>(self) -> &'a [T] {
let base = unsafe { mem::transmute(self.base) };
let len = self.size / mem::size_of::<T>();
unsafe { slice::from_raw_parts(base, len) }
}
pub fn as_mut_slice<T: BinaryViewType>(self) -> &'a mut [T] {
let base = unsafe { mem::transmute(self.base) };
let len = self.size / mem::size_of::<T>();
unsafe { slice::from_raw_parts_mut(base, len) }
}
pub fn len(self) -> usize {
self.size
}
}
impl<'a> Borrow for &'a JsBuffer {
type Target = BinaryData<'a>;
fn try_borrow<'b>(self, guard: &'b Lock<'b>) -> Result<Ref<'b, Self::Target>, LoanError> {
let mut data = MaybeUninit::<BinaryData>::uninit();
unsafe {
let pointer = data.as_mut_ptr();
(*pointer).size = neon_runtime::buffer::data(&mut (*pointer).base, self.to_raw());
}
unsafe {
Ref::new(guard, data.assume_init())
}
}
}
impl<'a> Borrow for &'a mut JsBuffer {
type Target = BinaryData<'a>;
fn try_borrow<'b>(self, guard: &'b Lock<'b>) -> Result<Ref<'b, Self::Target>, LoanError> {
(self as &'a JsBuffer).try_borrow(guard)
}
}
impl<'a> BorrowMut for &'a mut JsBuffer {
fn try_borrow_mut<'b>(self, guard: &'b Lock<'b>) -> Result<RefMut<'b, Self::Target>, LoanError> {
let mut data = MaybeUninit::<BinaryData>::uninit();
unsafe {
let pointer = data.as_mut_ptr();
(*pointer).size = neon_runtime::buffer::data(&mut (*pointer).base, self.to_raw());
}
unsafe {
RefMut::new(guard, data.assume_init())
}
}
}
impl<'a> Borrow for &'a JsArrayBuffer {
type Target = BinaryData<'a>;
fn try_borrow<'b>(self, guard: &'b Lock<'b>) -> Result<Ref<'b, Self::Target>, LoanError> {
let mut data = MaybeUninit::<BinaryData>::uninit();
unsafe {
let pointer = data.as_mut_ptr();
(*pointer).size = neon_runtime::arraybuffer::data(&mut (*pointer).base, self.to_raw());
}
unsafe {
Ref::new(guard, data.assume_init())
}
}
}
impl<'a> Borrow for &'a mut JsArrayBuffer {
type Target = BinaryData<'a>;
fn try_borrow<'b>(self, guard: &'b Lock<'b>) -> Result<Ref<'b, Self::Target>, LoanError> {
(self as &'a JsArrayBuffer).try_borrow(guard)
}
}
impl<'a> BorrowMut for &'a mut JsArrayBuffer {
fn try_borrow_mut<'b>(self, guard: &'b Lock<'b>) -> Result<RefMut<'b, Self::Target>, LoanError> {
let mut data = MaybeUninit::<BinaryData>::uninit();
unsafe {
let pointer = data.as_mut_ptr();
(*pointer).size = neon_runtime::arraybuffer::data(&mut (*pointer).base, self.to_raw());
}
unsafe {
RefMut::new(guard, data.assume_init())
}
}
}