// // JSITypedArray.h // VisionCamera // // Created by Marc Rousavy on 21.02.23. // Copyright © 2023 mrousavy. All rights reserved. // // Copied & Adapted from https://github.com/expo/expo/blob/main/packages/expo-gl/common/EXTypedArrayApi.h // Credits to Expo #pragma once #include namespace jsi = facebook::jsi; namespace vision { enum class TypedArrayKind { Int8Array, Int16Array, Int32Array, Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array, Float32Array, Float64Array, }; template class TypedArray; template struct typedArrayTypeMap; template <> struct typedArrayTypeMap { typedef int8_t type; }; template <> struct typedArrayTypeMap { typedef int16_t type; }; template <> struct typedArrayTypeMap { typedef int32_t type; }; template <> struct typedArrayTypeMap { typedef uint8_t type; }; template <> struct typedArrayTypeMap { typedef uint8_t type; }; template <> struct typedArrayTypeMap { typedef uint16_t type; }; template <> struct typedArrayTypeMap { typedef uint32_t type; }; template <> struct typedArrayTypeMap { typedef float type; }; template <> struct typedArrayTypeMap { typedef double type; }; // Instance of this class will invalidate PropNameIDCache when destructor is called. // Attach this object to global in specific jsi::Runtime to make sure lifecycle of // the cache object is connected to the lifecycle of the js runtime class InvalidateCacheOnDestroy : public jsi::HostObject { public: InvalidateCacheOnDestroy(jsi::Runtime &runtime); virtual ~InvalidateCacheOnDestroy(); virtual jsi::Value get(jsi::Runtime &, const jsi::PropNameID &name) { return jsi::Value::null(); } virtual void set(jsi::Runtime &, const jsi::PropNameID &name, const jsi::Value &value) {} virtual std::vector getPropertyNames(jsi::Runtime &rt) { return {}; } private: uintptr_t key; }; class TypedArrayBase : public jsi::Object { public: template using ContentType = typename typedArrayTypeMap::type; TypedArrayBase(jsi::Runtime &, size_t, TypedArrayKind); TypedArrayBase(jsi::Runtime &, const jsi::Object &); TypedArrayBase(TypedArrayBase &&) = default; TypedArrayBase &operator=(TypedArrayBase &&) = default; TypedArrayKind getKind(jsi::Runtime &runtime) const; template TypedArray get(jsi::Runtime &runtime) const &; template TypedArray get(jsi::Runtime &runtime) &&; template TypedArray as(jsi::Runtime &runtime) const &; template TypedArray as(jsi::Runtime &runtime) &&; size_t size(jsi::Runtime &runtime) const; size_t length(jsi::Runtime &runtime) const; size_t byteLength(jsi::Runtime &runtime) const; size_t byteOffset(jsi::Runtime &runtime) const; bool hasBuffer(jsi::Runtime &runtime) const; std::vector toVector(jsi::Runtime &runtime); jsi::ArrayBuffer getBuffer(jsi::Runtime &runtime) const; private: template friend class TypedArray; }; bool isTypedArray(jsi::Runtime &runtime, const jsi::Object &jsObj); TypedArrayBase getTypedArray(jsi::Runtime &runtime, const jsi::Object &jsObj); std::vector arrayBufferToVector(jsi::Runtime &runtime, jsi::Object &jsObj); void arrayBufferUpdate( jsi::Runtime &runtime, jsi::ArrayBuffer &buffer, std::vector data, size_t offset); template class TypedArray : public TypedArrayBase { public: TypedArray(jsi::Runtime &runtime, size_t size); TypedArray(jsi::Runtime &runtime, std::vector> data); TypedArray(TypedArrayBase &&base); TypedArray(TypedArray &&) = default; TypedArray &operator=(TypedArray &&) = default; std::vector> toVector(jsi::Runtime &runtime); void update(jsi::Runtime &runtime, const std::vector> &data); void updateUnsafe(jsi::Runtime &runtime, ContentType *data, size_t length); uint8_t* data(jsi::Runtime &runtime); }; template TypedArray TypedArrayBase::get(jsi::Runtime &runtime) const & { assert(getKind(runtime) == T); (void)runtime; // when assert is disabled we need to mark this as used return TypedArray(jsi::Value(runtime, jsi::Value(runtime, *this).asObject(runtime))); } template TypedArray TypedArrayBase::get(jsi::Runtime &runtime) && { assert(getKind(runtime) == T); (void)runtime; // when assert is disabled we need to mark this as used return TypedArray(std::move(*this)); } template TypedArray TypedArrayBase::as(jsi::Runtime &runtime) const & { if (getKind(runtime) != T) { throw jsi::JSError(runtime, "Object is not a TypedArray"); } return get(runtime); } template TypedArray TypedArrayBase::as(jsi::Runtime &runtime) && { if (getKind(runtime) != T) { throw jsi::JSError(runtime, "Object is not a TypedArray"); } return std::move(*this).get(runtime); } } // namespace vision