use crate::{
FromJSValue, HostError, IntoJSValue, JSContext, JSObject, JSObjectOps, JSResult, JSTypeOf,
JSValue, JSValueImpl, JSValueMapper, TypedArrayElement,
};
use std::ops::{Deref, DerefMut};
pub struct JSArrayBuffer<V: JSValueImpl> {
inner: JSObject<V>,
}
impl<V: JSValueImpl> Deref for JSArrayBuffer<V> {
type Target = JSObject<V>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<V: JSValueImpl> DerefMut for JSArrayBuffer<V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<V: JSValueImpl> Clone for JSArrayBuffer<V> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<V> IntoJSValue<V> for JSArrayBuffer<V>
where
V: JSValueImpl,
{
fn into_js_value(self, _ctx: &JSContext<V::Context>) -> JSValue<V> {
self.inner.into_js_value()
}
}
impl<V> FromJSValue<V> for JSArrayBuffer<V>
where
V: JSTypeOf,
{
fn from_js_value(ctx: &JSContext<V::Context>, value: JSValue<V>) -> JSResult<Self> {
if value.is_array_buffer() {
Ok(Self {
inner: JSObject::from_js_value(ctx, value)?,
})
} else {
Err(HostError::not_array_buffer().into())
}
}
}
pub trait JSArrayBufferOps: JSValueImpl {
fn from_bytes(ctx: &Self::Context, bytes: &[u8]) -> Self;
fn from_vec(ctx: &Self::Context, vec: Vec<u8>) -> Self;
fn length(&self) -> usize;
fn as_slice(&self) -> &[u8];
fn as_mut_slice(&mut self) -> &mut [u8];
}
impl<V> JSArrayBuffer<V>
where
V: JSObjectOps + JSArrayBufferOps,
{
pub fn from_bytes(ctx: &JSContext<V::Context>, bytes: &[u8]) -> JSResult<Self> {
let value = V::from_bytes(ctx.as_ref(), bytes);
value.try_map(|value| Self::from_js_value(ctx, JSValue::from_raw(ctx, value)))?
}
pub fn from_bytes_owned<B: Into<Vec<u8>>>(
ctx: &JSContext<V::Context>,
data: B,
) -> JSResult<Self> {
let value = V::from_vec(ctx.as_ref(), data.into());
value.try_map(|value| Self::from_js_value(ctx, JSValue::from_raw(ctx, value)))?
}
pub fn len(&self) -> usize {
self.as_value().length()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn as_slice(&self) -> &[u8] {
self.as_value().as_slice()
}
pub fn as_bytes(&self) -> &[u8] {
self.as_slice()
}
pub fn as_mut_slice(&mut self) -> &mut [u8] {
self.as_mut_value().as_mut_slice()
}
pub fn slice(&self, start: usize, end: usize) -> &[u8] {
&self.as_slice()[start..end]
}
pub fn to_vec(&self) -> Vec<u8> {
self.as_slice().to_vec()
}
pub fn element_count<T>(&self) -> JSResult<usize>
where
T: TypedArrayElement,
{
if !self.len().is_multiple_of(T::BYTES_PER_ELEMENT) {
return Err(HostError::typed_array_alignment_error().into());
}
Ok(self.len() / T::BYTES_PER_ELEMENT)
}
pub fn validate_alignment<T>(&self, offset: usize) -> bool
where
T: TypedArrayElement,
{
offset.is_multiple_of(T::BYTES_PER_ELEMENT)
}
pub fn from_object(obj: JSObject<V>) -> Option<Self> {
if obj.as_value().is_array_buffer() {
Some(Self { inner: obj })
} else {
None
}
}
}
impl<V: JSValueImpl> crate::function::JSParameterType for JSArrayBuffer<V> {}