Page MenuHomePhabricator

D7973.diff
No OneTemporary

D7973.diff

diff --git a/native/expo-modules/comm-expo-package/expo-module.config.json b/native/expo-modules/comm-expo-package/expo-module.config.json
--- a/native/expo-modules/comm-expo-package/expo-module.config.json
+++ b/native/expo-modules/comm-expo-package/expo-module.config.json
@@ -1,7 +1,7 @@
{
"platforms": ["ios", "android"],
"ios": {
- "modules": ["AESCryptoModule", "ThumbhashModule"]
+ "modules": ["AESCryptoModule", "BlobUtilsModule", "ThumbhashModule"]
},
"android": {
"modules": [
diff --git a/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift b/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift
--- a/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift
+++ b/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift
@@ -66,19 +66,6 @@
plaintext.copyBytes(to: destination.rawBufferPtr())
}
-// MARK: - Utilities
-
-extension TypedArray {
- func data() -> Data {
- Data(bytes: self.rawPointer, count: self.byteLength)
- }
-
- func rawBufferPtr() -> UnsafeMutableRawBufferPointer {
- UnsafeMutableRawBufferPointer(start: self.rawPointer,
- count: self.byteLength)
- }
-}
-
// MARK: - Exception definitions
private class InvalidKeyLengthException: Exception {
diff --git a/native/expo-modules/comm-expo-package/ios/BlobUtilsModule.swift b/native/expo-modules/comm-expo-package/ios/BlobUtilsModule.swift
new file mode 100644
--- /dev/null
+++ b/native/expo-modules/comm-expo-package/ios/BlobUtilsModule.swift
@@ -0,0 +1,70 @@
+import ExpoModulesCore
+
+// This type corresponds to the BlobData interface in react-native
+struct BlobMetadata: Record {
+ @Field var blobId: String
+ @Field var size: Int
+ @Field var offset: Int
+}
+
+public class BlobUtilsModule: Module {
+ public func definition() -> ModuleDefinition {
+ Name("BlobUtils")
+
+ Function("copyBlobToTypedArray") {
+ (blob: BlobMetadata, destination: Uint8Array) throws in
+ let blobManager = try self.getReactBlobManager()
+ guard let blobData = blobManager.resolve(blob.blobId,
+ offset: blob.offset,
+ size: blob.size) else {
+ throw NoSuchBlobException(blob.blobId)
+ }
+ blobData.copyBytes(to: destination.rawBufferPtr())
+ }
+
+ Function("blobFromTypedArray") { (source: TypedArray) throws -> String in
+ let blobManager = try self.getReactBlobManager()
+ guard let blobID = blobManager.store(source.data()) else {
+ throw BlobCreationFailedException()
+ }
+ return blobID
+ }
+ }
+
+ private func getReactBlobManager() throws -> RCTBlobManager {
+ guard let bridge = self.appContext?.reactBridge else {
+ throw BridgeNotFoundException()
+ }
+ guard let blobManager = bridge.module(for: RCTBlobManager.self)
+ as? RCTBlobManager else {
+ throw BlobManagerNotFoundException()
+ }
+ return blobManager
+ }
+}
+
+// MARK: Exception definitions
+
+class BridgeNotFoundException: Exception {
+ override var reason: String {
+ "React bridge is null"
+ }
+}
+
+class BlobManagerNotFoundException: Exception {
+ override var reason: String {
+ "Module RCTBlobManager not found"
+ }
+}
+
+class NoSuchBlobException: GenericException<String> {
+ override var reason: String {
+ "No blob data found for blob id=\(param)"
+ }
+}
+
+class BlobCreationFailedException: Exception {
+ override var reason: String {
+ "Failed to store blob"
+ }
+}
diff --git a/native/expo-modules/comm-expo-package/ios/TypedArray+data.swift b/native/expo-modules/comm-expo-package/ios/TypedArray+data.swift
new file mode 100644
--- /dev/null
+++ b/native/expo-modules/comm-expo-package/ios/TypedArray+data.swift
@@ -0,0 +1,12 @@
+import ExpoModulesCore
+
+extension TypedArray {
+ func data() -> Data {
+ Data(bytes: self.rawPointer, count: self.byteLength)
+ }
+
+ func rawBufferPtr() -> UnsafeMutableRawBufferPointer {
+ UnsafeMutableRawBufferPointer(start: self.rawPointer,
+ count: self.byteLength)
+ }
+}
diff --git a/native/utils/blob-utils-module.js b/native/utils/blob-utils-module.js
new file mode 100644
--- /dev/null
+++ b/native/utils/blob-utils-module.js
@@ -0,0 +1,44 @@
+// @flow
+
+import { requireNativeModule } from 'expo-modules-core';
+import RNBlob from 'react-native/Libraries/Blob/Blob.js';
+import BlobManager from 'react-native/Libraries/Blob/BlobManager.js';
+import type { BlobData } from 'react-native/Libraries/Blob/BlobTypes.js';
+
+const BlobUtilsModule: {
+ +copyBlobToTypedArray: (blob: BlobData, destination: Uint8Array) => void,
+ +blobFromTypedArray: (data: $TypedArray) => string,
+} = requireNativeModule('BlobUtils');
+
+function arrayBufferFromBlob(blob: Blob): ArrayBuffer {
+ // $FlowFixMe: react-native Blob type is incompatible with global Blob type
+ const rnBlob = (blob: RNBlob);
+ if (!(rnBlob instanceof RNBlob)) {
+ throw new Error(
+ 'Given blob is not a React Native blob. Missing "data" property.',
+ );
+ }
+ const blobData = rnBlob.data;
+
+ const resultArray = new Uint8Array(blob.size);
+ BlobUtilsModule.copyBlobToTypedArray(blobData, resultArray);
+ return resultArray.buffer;
+}
+
+function blobFromArrayBuffer(arrayBuffer: ArrayBuffer, type?: string): Blob {
+ const typedArray = new Uint8Array(arrayBuffer);
+ const blobID = BlobUtilsModule.blobFromTypedArray(typedArray);
+ const reactNativeBlob = BlobManager.createFromOptions({
+ blobId: blobID,
+ offset: 0,
+ size: arrayBuffer.byteLength,
+ type: type || '',
+ lastModified: Date.now(),
+ });
+
+ // $FlowFixMe: react-native Blob type is incompatible with global Blob type
+ // $FlowFixMe: even though they have the same properties
+ return (reactNativeBlob: Blob);
+}
+
+export { arrayBufferFromBlob, blobFromArrayBuffer };

File Metadata

Mime Type
text/plain
Expires
Thu, Dec 5, 1:17 AM (13 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2615426
Default Alt Text
D7973.diff (5 KB)

Event Timeline