1 #pragma once 2 3 #include <jsi/jsi.h> 4 5 namespace jsi = facebook::jsi; 6 namespace expo { 7 namespace gl_cpp { 8 9 enum class TypedArrayKind { 10 Int8Array, 11 Int16Array, 12 Int32Array, 13 Uint8Array, 14 Uint8ClampedArray, 15 Uint16Array, 16 Uint32Array, 17 Float32Array, 18 Float64Array, 19 }; 20 21 template <TypedArrayKind T> 22 class TypedArray; 23 24 template <TypedArrayKind T> 25 struct typedArrayTypeMap; 26 template <> 27 struct typedArrayTypeMap<TypedArrayKind::Int8Array> { 28 typedef int8_t type; 29 }; 30 template <> 31 struct typedArrayTypeMap<TypedArrayKind::Int16Array> { 32 typedef int16_t type; 33 }; 34 template <> 35 struct typedArrayTypeMap<TypedArrayKind::Int32Array> { 36 typedef int32_t type; 37 }; 38 template <> 39 struct typedArrayTypeMap<TypedArrayKind::Uint8Array> { 40 typedef uint8_t type; 41 }; 42 template <> 43 struct typedArrayTypeMap<TypedArrayKind::Uint8ClampedArray> { 44 typedef uint8_t type; 45 }; 46 template <> 47 struct typedArrayTypeMap<TypedArrayKind::Uint16Array> { 48 typedef uint16_t type; 49 }; 50 template <> 51 struct typedArrayTypeMap<TypedArrayKind::Uint32Array> { 52 typedef uint32_t type; 53 }; 54 template <> 55 struct typedArrayTypeMap<TypedArrayKind::Float32Array> { 56 typedef float type; 57 }; 58 template <> 59 struct typedArrayTypeMap<TypedArrayKind::Float64Array> { 60 typedef double type; 61 }; 62 63 // Instance of this class will invalidate PropNameIDCache when destructor is called. 64 // Attach this object to global in specific jsi::Runtime to make sure lifecycle of 65 // the cache object is connected to the lifecycle of the js runtime 66 class InvalidateCacheOnDestroy : public jsi::HostObject { 67 public: 68 InvalidateCacheOnDestroy(jsi::Runtime &runtime); 69 virtual ~InvalidateCacheOnDestroy(); 70 virtual jsi::Value get(jsi::Runtime &, const jsi::PropNameID &name) { 71 return jsi::Value::null(); 72 } 73 virtual void set(jsi::Runtime &, const jsi::PropNameID &name, const jsi::Value &value) {} 74 virtual std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) { 75 return {}; 76 } 77 78 private: 79 uintptr_t key; 80 }; 81 82 class TypedArrayBase : public jsi::Object { 83 public: 84 template <TypedArrayKind T> 85 using ContentType = typename typedArrayTypeMap<T>::type; 86 87 TypedArrayBase(jsi::Runtime &, size_t, TypedArrayKind); 88 TypedArrayBase(jsi::Runtime &, const jsi::Object &); 89 TypedArrayBase(TypedArrayBase &&) = default; 90 TypedArrayBase &operator=(TypedArrayBase &&) = default; 91 92 TypedArrayKind getKind(jsi::Runtime &runtime) const; 93 94 template <TypedArrayKind T> 95 TypedArray<T> get(jsi::Runtime &runtime) const &; 96 template <TypedArrayKind T> 97 TypedArray<T> get(jsi::Runtime &runtime) &&; 98 template <TypedArrayKind T> 99 TypedArray<T> as(jsi::Runtime &runtime) const &; 100 template <TypedArrayKind T> 101 TypedArray<T> as(jsi::Runtime &runtime) &&; 102 103 size_t size(jsi::Runtime &runtime) const; 104 size_t length(jsi::Runtime &runtime) const; 105 size_t byteLength(jsi::Runtime &runtime) const; 106 size_t byteOffset(jsi::Runtime &runtime) const; 107 bool hasBuffer(jsi::Runtime &runtime) const; 108 109 std::vector<uint8_t> toVector(jsi::Runtime &runtime); 110 jsi::ArrayBuffer getBuffer(jsi::Runtime &runtime) const; 111 112 private: 113 template <TypedArrayKind> 114 friend class TypedArray; 115 }; 116 117 bool isTypedArray(jsi::Runtime &runtime, const jsi::Object &jsObj); 118 TypedArrayBase getTypedArray(jsi::Runtime &runtime, const jsi::Object &jsObj); 119 120 std::vector<uint8_t> arrayBufferToVector(jsi::Runtime &runtime, jsi::Object &jsObj); 121 void arrayBufferUpdate( 122 jsi::Runtime &runtime, 123 jsi::ArrayBuffer &buffer, 124 std::vector<uint8_t> data, 125 size_t offset); 126 127 template <TypedArrayKind T> 128 class TypedArray : public TypedArrayBase { 129 public: 130 TypedArray(jsi::Runtime &runtime, size_t size); 131 TypedArray(jsi::Runtime &runtime, std::vector<ContentType<T>> data); 132 TypedArray(TypedArrayBase &&base); 133 TypedArray(TypedArray &&) = default; 134 TypedArray &operator=(TypedArray &&) = default; 135 136 std::vector<ContentType<T>> toVector(jsi::Runtime &runtime); 137 void update(jsi::Runtime &runtime, const std::vector<ContentType<T>> &data); 138 }; 139 140 template <TypedArrayKind T> 141 TypedArray<T> TypedArrayBase::get(jsi::Runtime &runtime) const & { 142 assert(getKind(runtime) == T); 143 (void)runtime; // when assert is disabled we need to mark this as used 144 return TypedArray<T>(jsi::Value(runtime, jsi::Value(runtime, *this).asObject(runtime))); 145 } 146 147 template <TypedArrayKind T> 148 TypedArray<T> TypedArrayBase::get(jsi::Runtime &runtime) && { 149 assert(getKind(runtime) == T); 150 (void)runtime; // when assert is disabled we need to mark this as used 151 return TypedArray<T>(std::move(*this)); 152 } 153 154 template <TypedArrayKind T> 155 TypedArray<T> TypedArrayBase::as(jsi::Runtime &runtime) const & { 156 if (getKind(runtime) != T) { 157 throw jsi::JSError(runtime, "Object is not a TypedArray"); 158 } 159 return get<T>(runtime); 160 } 161 162 template <TypedArrayKind T> 163 TypedArray<T> TypedArrayBase::as(jsi::Runtime &runtime) && { 164 if (getKind(runtime) != T) { 165 throw jsi::JSError(runtime, "Object is not a TypedArray"); 166 } 167 return std::move(*this).get<T>(runtime); 168 } 169 } // namespace gl_cpp 170 } // namespace expo 171