use super::*;
use rquickjs::{ArrayBuffer, Function, Object};
pub(super) unsafe fn view_ptr(buffer: V, offset: usize, byte_length: usize) -> Status<*mut c_void> {
let ab = ArrayBuffer::from_value(buffer).ok_or(NAPI_INVALID_ARG)?;
let raw = ab.as_raw().ok_or(NAPI_INVALID_ARG)?;
let end = offset.checked_add(byte_length).ok_or(NAPI_INVALID_ARG)?;
if end > raw.len() {
return Err(NAPI_INVALID_ARG);
}
Ok((raw.as_ptr() as *mut u8).add(offset) as *mut c_void)
}
pub(super) unsafe fn buf_info(env: napi_env, value: napi_value) -> Status<(usize, usize, V)> {
let value = get(value)?;
if !is_array_buffer_view(env, value)? {
return Err(NAPI_INVALID_ARG);
}
let view = value.as_object().ok_or(NAPI_INVALID_ARG)?;
let byte_length = js(env, view.get("byteLength"))?;
let byte_offset = js(env, view.get("byteOffset"))?;
let buffer = js(env, view.get("buffer"))?;
Ok((byte_length, byte_offset, buffer))
}
pub(super) unsafe fn is_array_buffer_view(env: napi_env, value: &V) -> Status<bool> {
let globals = ctx(env).globals();
let array_buffer: Object = js(env, globals.get("ArrayBuffer"))?;
let is_view: Function = js(env, array_buffer.get("isView"))?;
js(env, is_view.call((value.clone(),)))
}
#[allow(clippy::unnecessary_cast)]
pub(super) unsafe fn view_info(
env: napi_env,
value: napi_value,
) -> Status<(u32, usize, usize, usize, V)> {
let value = get(value)?;
let kind = qjs::JS_GetTypedArrayType(value.as_raw());
if kind < 0 {
return Err(NAPI_INVALID_ARG);
}
let mut offset = 0;
let mut byte_length = 0;
let mut bytes_per_element = 0;
let raw_buffer = qjs::JS_GetTypedArrayBuffer(
ctx(env).as_raw().as_ptr(),
value.as_raw(),
&mut offset,
&mut byte_length,
&mut bytes_per_element,
);
if qjs::JS_IsException(raw_buffer) {
(*env).exception = Some(extend(ctx(env).catch()));
return Err(NAPI_PENDING_EXCEPTION);
}
if bytes_per_element == 0 {
qjs::JS_FreeValue(ctx(env).as_raw().as_ptr(), raw_buffer);
return Err(NAPI_GENERIC_FAILURE);
}
let buffer = extend(Value::from_raw(ctx(env), raw_buffer));
const INT8: u32 = qjs::JSTypedArrayEnum_JS_TYPED_ARRAY_INT8 as u32;
const UINT8: u32 = qjs::JSTypedArrayEnum_JS_TYPED_ARRAY_UINT8 as u32;
const UINT8C: u32 = qjs::JSTypedArrayEnum_JS_TYPED_ARRAY_UINT8C as u32;
const INT16: u32 = qjs::JSTypedArrayEnum_JS_TYPED_ARRAY_INT16 as u32;
const UINT16: u32 = qjs::JSTypedArrayEnum_JS_TYPED_ARRAY_UINT16 as u32;
const INT32: u32 = qjs::JSTypedArrayEnum_JS_TYPED_ARRAY_INT32 as u32;
const UINT32: u32 = qjs::JSTypedArrayEnum_JS_TYPED_ARRAY_UINT32 as u32;
const FLOAT32: u32 = qjs::JSTypedArrayEnum_JS_TYPED_ARRAY_FLOAT32 as u32;
const FLOAT64: u32 = qjs::JSTypedArrayEnum_JS_TYPED_ARRAY_FLOAT64 as u32;
const BIG_INT64: u32 = qjs::JSTypedArrayEnum_JS_TYPED_ARRAY_BIG_INT64 as u32;
const BIG_UINT64: u32 = qjs::JSTypedArrayEnum_JS_TYPED_ARRAY_BIG_UINT64 as u32;
let napi_kind = match kind as u32 {
INT8 => 0,
UINT8 => 1,
UINT8C => 2,
INT16 => 3,
UINT16 => 4,
INT32 => 5,
UINT32 => 6,
FLOAT32 => 7,
FLOAT64 => 8,
BIG_INT64 => 9,
BIG_UINT64 => 10,
_ => 1,
};
Ok((
napi_kind,
(byte_length / bytes_per_element) as usize,
offset as usize,
byte_length as usize,
buffer,
))
}