react-native-nitro-modules 0.20.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -107,19 +107,40 @@ class ArrayBuffer {
107
107
  /**
108
108
  * Copy the given `ArrayBuffer` into a new **owning** `ArrayBuffer`.
109
109
  */
110
- fun copyOf(other: ArrayBuffer): ArrayBuffer {
111
- // 1. Create a new buffer with the same size as the other
112
- val newBuffer = ByteBuffer.allocateDirect(other.size)
113
- // 2. Prepare the source buffer
114
- val originalBuffer = other.getBuffer(false)
115
- originalBuffer.rewind()
110
+ fun copy(other: ArrayBuffer): ArrayBuffer {
111
+ val byteBuffer = other.getBuffer(false)
112
+ return copy(byteBuffer)
113
+ }
114
+
115
+ /**
116
+ * Copy the given `ByteBuffer` into a new **owning** `ArrayBuffer`.
117
+ */
118
+ fun copy(byteBuffer: ByteBuffer): ArrayBuffer {
119
+ // 1. Find out size
120
+ byteBuffer.rewind()
121
+ val size = byteBuffer.remaining()
122
+ // 2. Create a new buffer with the same size as the other
123
+ val newBuffer = ByteBuffer.allocateDirect(size)
116
124
  // 3. Copy over the source buffer into the new buffer
117
- newBuffer.put(originalBuffer)
125
+ newBuffer.put(byteBuffer)
118
126
  // 4. Rewind both buffers again to index 0
119
127
  newBuffer.rewind()
120
- originalBuffer.rewind()
128
+ byteBuffer.rewind()
121
129
  // 5. Create a new `ArrayBuffer`
122
130
  return ArrayBuffer(newBuffer)
123
131
  }
132
+
133
+ /**
134
+ * Wrap the given `ByteBuffer` in a new **owning** `ArrayBuffer`.
135
+ */
136
+ fun wrap(byteBuffer: ByteBuffer): ArrayBuffer {
137
+ byteBuffer.rewind()
138
+ return ArrayBuffer(byteBuffer)
139
+ }
140
+
141
+ @Deprecated("Use copy(...) instead", level = DeprecationLevel.WARNING)
142
+ fun copyOf(other: ArrayBuffer): ArrayBuffer {
143
+ return copy(other)
144
+ }
124
145
  }
125
146
  }
@@ -23,7 +23,7 @@ abstract class HybridObject: ExtendableHybridClass {
23
23
  *
24
24
  * @example
25
25
  * ```kotlin
26
- * val memorySize: ULong
26
+ * override val memorySize: ULong
27
27
  * get() {
28
28
  * val imageSize = this.bitmap.bytesPerRow * this.bitmap.height
29
29
  * return imageSize
@@ -17,10 +17,25 @@ using namespace facebook;
17
17
 
18
18
  // 1. ArrayBuffer
19
19
 
20
- std::shared_ptr<ArrayBuffer> ArrayBuffer::makeBuffer(uint8_t* data, size_t size, DeleteFn&& deleteFunc) {
20
+ std::shared_ptr<ArrayBuffer> ArrayBuffer::wrap(uint8_t* data, size_t size, DeleteFn&& deleteFunc) {
21
21
  return std::make_shared<NativeArrayBuffer>(data, size, std::move(deleteFunc));
22
22
  }
23
23
 
24
+ std::shared_ptr<ArrayBuffer> ArrayBuffer::copy(uint8_t* data, size_t size) {
25
+ uint8_t* copy = new uint8_t[size];
26
+ std::memcpy(copy, data, size);
27
+ return ArrayBuffer::wrap(copy, size, [=]() { delete[] copy; });
28
+ }
29
+
30
+ std::shared_ptr<ArrayBuffer> ArrayBuffer::copy(std::vector<uint8_t>& data) {
31
+ return ArrayBuffer::copy(data.data(), data.size());
32
+ }
33
+
34
+ std::shared_ptr<ArrayBuffer> ArrayBuffer::allocate(size_t size) {
35
+ uint8_t* data = new uint8_t[size];
36
+ return ArrayBuffer::wrap(data, size, [=]() { delete[] data; });
37
+ }
38
+
24
39
  // 2. NativeArrayBuffer
25
40
 
26
41
  NativeArrayBuffer::NativeArrayBuffer(uint8_t* data, size_t size, DeleteFn&& deleteFunc)
@@ -10,6 +10,7 @@
10
10
  #include "OwningReference.hpp"
11
11
  #include <jsi/jsi.h>
12
12
  #include <thread>
13
+ #include <vector>
13
14
 
14
15
  namespace margelo::nitro {
15
16
 
@@ -52,7 +53,25 @@ public:
52
53
  * Create a new `NativeArrayBuffer` that wraps the given data (without copy) of the given size,
53
54
  * and calls `deleteFunc` in which `data` should be deleted.
54
55
  */
55
- static std::shared_ptr<ArrayBuffer> makeBuffer(uint8_t* data, size_t size, DeleteFn&& deleteFunc);
56
+ static std::shared_ptr<ArrayBuffer> wrap(uint8_t* data, size_t size, DeleteFn&& deleteFunc);
57
+ /**
58
+ * Create a new `NativeArrayBuffer` that copies the given data of the given size
59
+ * into a newly allocated buffer.
60
+ */
61
+ static std::shared_ptr<ArrayBuffer> copy(uint8_t* data, size_t size);
62
+ /**
63
+ * Create a new `NativeArrayBuffer` that copies the given `std::vector`.
64
+ */
65
+ static std::shared_ptr<ArrayBuffer> copy(std::vector<uint8_t>& data);
66
+ /**
67
+ * Create a new `NativeArrayBuffer` that allocates a new buffer of the given size.
68
+ */
69
+ static std::shared_ptr<ArrayBuffer> allocate(size_t size);
70
+
71
+ [[deprecated("Use wrapBuffer(...) instead.")]]
72
+ static std::shared_ptr<ArrayBuffer> makeBuffer(uint8_t* data, size_t size, DeleteFn&& deleteFunc) {
73
+ return ArrayBuffer::wrap(data, size, std::move(deleteFunc));
74
+ }
56
75
  };
57
76
 
58
77
  /**
@@ -9,7 +9,7 @@
9
9
  #define NitroDefines_h
10
10
 
11
11
  // Sets the version of the native Nitro core library
12
- #define NITRO_VERSION "0.20.1"
12
+ #define NITRO_VERSION "0.21.0"
13
13
 
14
14
  // Sets whether to use debug or optimized production build flags
15
15
  #ifdef DEBUG
@@ -35,9 +35,9 @@ public:
35
35
  * Once the `ArrayBuffer` is no longer in use, the given `deleteFunc` will be called with the given `deleteFuncContext`
36
36
  * as an argument. The caller is responsible for deleting `data` once this is called.
37
37
  */
38
- static ArrayBufferHolder makeBuffer(uint8_t* _Nonnull data, size_t size, SwiftClosure destroy) {
38
+ static ArrayBufferHolder wrap(uint8_t* _Nonnull data, size_t size, SwiftClosure destroy) {
39
39
  std::function<void()> deleteFunc = destroy.getFunction();
40
- auto arrayBuffer = ArrayBuffer::makeBuffer(data, size, std::move(deleteFunc));
40
+ auto arrayBuffer = ArrayBuffer::wrap(data, size, std::move(deleteFunc));
41
41
  return ArrayBufferHolder(arrayBuffer);
42
42
  }
43
43
 
@@ -45,7 +45,7 @@ public:
45
45
  /**
46
46
  * Gets the raw bytes the underlying `ArrayBuffer` points to.
47
47
  */
48
- void* _Nonnull getData() const SWIFT_COMPUTED_PROPERTY {
48
+ uint8_t* _Nonnull getData() const SWIFT_COMPUTED_PROPERTY {
49
49
  return _arrayBuffer->data();
50
50
  }
51
51
  /**
@@ -15,6 +15,8 @@ import Foundation
15
15
  */
16
16
  public typealias ArrayBufferHolder = margelo.nitro.ArrayBufferHolder
17
17
 
18
+ // pragma MARK: Wrap
19
+
18
20
  public extension ArrayBufferHolder {
19
21
  /**
20
22
  * Create a new `ArrayBufferHolder` that wraps the given `data` of the given `size`
@@ -28,9 +30,27 @@ public extension ArrayBufferHolder {
28
30
  // Convert escaping Swift closure to a `void*`
29
31
  let swiftClosure = SwiftClosure(wrappingClosure: delete)
30
32
  // Create ArrayBufferHolder with our wrapped Swift closure to make it callable as a C-function pointer
31
- return ArrayBufferHolder.makeBuffer(data, size, swiftClosure)
33
+ return ArrayBufferHolder.wrap(data, size, swiftClosure)
32
34
  }
33
35
 
36
+ /**
37
+ * Create a new `ArrayBufferHolder` that wraps the given `data` of the given `size`
38
+ * without performing a copy.
39
+ * When the `ArrayBuffer` is no longer used, `onDelete` will be called, in which
40
+ * you as a caller are responsible for deleting `data`.
41
+ */
42
+ static func wrap(dataWithoutCopy data: UnsafeMutableRawPointer,
43
+ size: Int,
44
+ onDelete delete: @escaping () -> Void) -> ArrayBufferHolder {
45
+ return ArrayBufferHolder.wrap(dataWithoutCopy: data.assumingMemoryBound(to: UInt8.self),
46
+ size: size,
47
+ onDelete: delete)
48
+ }
49
+ }
50
+
51
+ // pragma MARK: Allocate
52
+
53
+ public extension ArrayBufferHolder {
34
54
  /**
35
55
  * Allocate a new buffer of the given `size`.
36
56
  * If `initializeToZero` is `true`, all bytes are set to `0`, otherwise they are left untouched.
@@ -40,24 +60,92 @@ public extension ArrayBufferHolder {
40
60
  if initializeToZero {
41
61
  data.initialize(repeating: 0, count: size)
42
62
  }
43
-
44
63
  let deleteFunc = SwiftClosure {
45
64
  data.deallocate()
46
65
  }
47
- return ArrayBufferHolder.makeBuffer(data, size, deleteFunc)
66
+ return ArrayBufferHolder.wrap(data, size, deleteFunc)
67
+ }
68
+ }
69
+
70
+ // pragma MARK: Copy
71
+
72
+ public extension ArrayBufferHolder {
73
+ /**
74
+ * Copy the given `UnsafeMutablePointer<UInt8>` into a new **owning** `ArrayBufferHolder`.
75
+ */
76
+ static func copy(of other: UnsafeMutablePointer<UInt8>,
77
+ size: Int) -> ArrayBufferHolder {
78
+ // 1. Create new `UnsafeMutablePointer<UInt8>`
79
+ let copy = UnsafeMutablePointer<UInt8>.allocate(capacity: size)
80
+ // 2. Copy over data
81
+ copy.initialize(from: other, count: size)
82
+ // 3. Create memory safe destroyer
83
+ let deleteFunc = SwiftClosure {
84
+ copy.deallocate()
85
+ }
86
+ return ArrayBufferHolder.wrap(copy, size, deleteFunc)
87
+ }
88
+
89
+ /**
90
+ * Copy the given `UnsafeMutableRawPointer` into a new **owning** `ArrayBufferHolder`.
91
+ */
92
+ static func copy(of other: UnsafeMutableRawPointer,
93
+ size: Int) -> ArrayBufferHolder {
94
+ return ArrayBufferHolder.copy(of: other.assumingMemoryBound(to: UInt8.self),
95
+ size: size)
48
96
  }
49
97
 
50
98
  /**
51
99
  * Copy the given `ArrayBufferHolder` into a new **owning** `ArrayBufferHolder`.
52
100
  */
53
101
  static func copy(of other: ArrayBufferHolder) -> ArrayBufferHolder {
54
- let data = UnsafeMutablePointer<UInt8>.allocate(capacity: other.size)
55
- let pointer = other.data.assumingMemoryBound(to: UInt8.self)
56
- data.initialize(from: pointer, count: other.size)
102
+ return ArrayBufferHolder.copy(of: other.data, size: other.size)
103
+ }
57
104
 
58
- let deleteFunc = SwiftClosure {
59
- data.deallocate()
105
+ /**
106
+ * Copy the given `Data` into a new **owning** `ArrayBufferHolder`.
107
+ */
108
+ static func copy(data: Data) throws -> ArrayBufferHolder {
109
+ // 1. Create new `ArrayBuffer` of same size
110
+ let size = data.count
111
+ let arrayBuffer = ArrayBufferHolder.allocate(size: size)
112
+ // 2. Copy all bytes from `Data` into our new `ArrayBuffer`
113
+ try data.withUnsafeBytes { rawPointer in
114
+ guard let baseAddress = rawPointer.baseAddress else {
115
+ throw RuntimeError.error(withMessage: "Cannot get baseAddress of Data!")
116
+ }
117
+ memcpy(arrayBuffer.data, baseAddress, size)
118
+ }
119
+ return arrayBuffer
120
+ }
121
+ }
122
+
123
+
124
+ // pragma MARK: Data
125
+
126
+ public extension ArrayBufferHolder {
127
+ /**
128
+ * Wrap this `ArrayBufferHolder` in a `Data` instance, without performing a copy.
129
+ * - `copyIfNeeded`: If this `ArrayBuffer` is **non-owning**, the foreign
130
+ * data may needs to be copied to be safely used outside of the scope of the caller function.
131
+ * This flag controls that.
132
+ */
133
+ func toData(copyIfNeeded: Bool) -> Data {
134
+ let shouldCopy = copyIfNeeded && !self.isOwner
135
+ if shouldCopy {
136
+ // COPY DATA
137
+ return Data.init(bytes: self.data, count: self.size)
138
+ } else {
139
+ // WRAP DATA
140
+ // 1. Get the std::shared_ptr<ArrayBuffer>
141
+ var sharedPointer = self.getArrayBuffer()
142
+ // 2. Create a Data object WRAPPING our pointer
143
+ return Data(bytesNoCopy: self.data, count: self.size, deallocator: .custom({ buffer, size in
144
+ // 3. Capture the std::shared_ptr<ArrayBuffer> in the deallocator lambda so it stays alive.
145
+ // As soon as this lambda gets called, the `sharedPointer` gets deleted causing the
146
+ // underlying `ArrayBuffer` to be freed.
147
+ sharedPointer.reset()
148
+ }))
60
149
  }
61
- return ArrayBufferHolder.makeBuffer(data, other.size, deleteFunc)
62
150
  }
63
151
  }
@@ -1,5 +1,5 @@
1
1
  //
2
- // ArrayBufferHolder.hpp
2
+ // PromiseHolder.hpp
3
3
  // react-native-nitro
4
4
  //
5
5
  // Created by Marc Rousavy on 14.08.24.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-modules",
3
- "version": "0.20.1",
3
+ "version": "0.21.0",
4
4
  "description": "Insanely fast native C++, Swift or Kotlin modules with a statically compiled binding layer to JSI.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -117,7 +117,6 @@
117
117
  [
118
118
  "typescript",
119
119
  {
120
- "tsc": "../../node_modules/.bin/tsc",
121
120
  "project": "tsconfig.build.json"
122
121
  }
123
122
  ]