use crate::borrow::internal::Pointer;
use crate::borrow::{Borrow, BorrowMut, LoanError, Ref, RefMut};
use crate::context::internal::Env;
use crate::context::{Context, Lock};
use crate::handle::{internal::TransparentNoCopyWrapper, Managed};
use crate::result::JsResult;
use crate::types::private::ValueInternal;
use crate::types::{build, Object, Value};
use neon_runtime;
use neon_runtime::raw;
use std::marker::PhantomData;
use std::mem::{self, MaybeUninit};
use std::os::raw::c_void;
use std::slice;
#[derive(Debug)]
#[repr(transparent)]
pub struct JsBuffer(raw::Local);
unsafe impl TransparentNoCopyWrapper for JsBuffer {
type Inner = raw::Local;
fn into_inner(self) -> Self::Inner {
self.0
}
}
impl JsBuffer {
pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> JsResult<'a, JsBuffer> {
let env = cx.env();
build(env, |out| unsafe {
neon_runtime::buffer::new(env.to_raw(), out, size)
})
}
pub unsafe fn uninitialized<'a, C: Context<'a>>(
cx: &mut C,
size: u32,
) -> JsResult<'a, JsBuffer> {
let env = cx.env();
build(env, |out| {
neon_runtime::buffer::uninitialized(env.to_raw(), out, size)
})
}
}
impl Managed for JsBuffer {
fn to_raw(&self) -> raw::Local {
self.0
}
fn from_raw(_env: Env, h: raw::Local) -> Self {
JsBuffer(h)
}
}
impl ValueInternal for JsBuffer {
fn name() -> String {
"Buffer".to_string()
}
fn is_typeof<Other: Value>(env: Env, other: &Other) -> bool {
unsafe { neon_runtime::tag::is_buffer(env.to_raw(), other.to_raw()) }
}
}
impl Value for JsBuffer {}
impl Object for JsBuffer {}
#[derive(Debug)]
#[repr(transparent)]
pub struct JsArrayBuffer(raw::Local);
impl JsArrayBuffer {
pub fn new<'a, C: Context<'a>>(cx: &mut C, size: u32) -> JsResult<'a, JsArrayBuffer> {
build(cx.env(), |out| unsafe {
neon_runtime::arraybuffer::new(out, mem::transmute(cx.env()), size)
})
}
}
unsafe impl TransparentNoCopyWrapper for JsArrayBuffer {
type Inner = raw::Local;
fn into_inner(self) -> Self::Inner {
self.0
}
}
impl Managed for JsArrayBuffer {
fn to_raw(&self) -> raw::Local {
self.0
}
fn from_raw(_env: Env, h: raw::Local) -> Self {
JsArrayBuffer(h)
}
}
impl ValueInternal for JsArrayBuffer {
fn name() -> String {
"ArrayBuffer".to_string()
}
fn is_typeof<Other: Value>(env: Env, other: &Other) -> bool {
unsafe { neon_runtime::tag::is_arraybuffer(env.to_raw(), 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] {
if self.size == 0 {
&[]
} else {
let base = self.base.cast();
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] {
if self.size == 0 {
&mut []
} else {
let base = self.base.cast();
let len = self.size / mem::size_of::<T>();
unsafe { slice::from_raw_parts_mut(base, len) }
}
}
pub fn len(self) -> usize {
self.size
}
pub fn is_empty(self) -> bool {
self.len() == 0
}
}
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(guard.env.to_raw(), &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(guard.env.to_raw(), &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(
guard.env.to_raw(),
&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(
guard.env.to_raw(),
&mut (*pointer).base,
self.to_raw(),
);
}
unsafe { RefMut::new(guard, data.assume_init()) }
}
}