diff --git a/README.md b/README.md index 01bfdc7..72bee57 100644 --- a/README.md +++ b/README.md @@ -297,7 +297,7 @@ await NitroFS.uploadFile(uploadOptions, (uploadedBytes, totalBytes) => { }) ``` -#### `downloadFile(downloadOptions: NitroDownloadOptions, onProgress?: (downloadedBytes: number, totalBytes: number) => void): Promise` +#### `downloadFile(downloadOptions: NitroDownloadOptions, onProgress?: (downloadedBytes: number, totalBytes: number) => void): Promise` Download a file from a server with progress tracking. @@ -310,7 +310,7 @@ const downloadOptions = { }, } -const downloadedFile = await NitroFS.downloadFile( +const downloadResult = await NitroFS.downloadFile( downloadOptions, (downloadedBytes, totalBytes) => { const progress = (downloadedBytes / totalBytes) * 100 @@ -318,10 +318,33 @@ const downloadedFile = await NitroFS.downloadFile( } ) +if (downloadResult instanceof ArrayBuffer) { + throw new Error('Expected file metadata') +} + +const downloadedFile = downloadResult console.log('Downloaded file:', downloadedFile) // Returns: { name: 'document.pdf', mimeType: 'application/pdf', path: '/path/to/file' } ``` +Return the downloaded bytes as a zero-copy `ArrayBuffer` by setting `output` to `'arrayBuffer'`. +The file is still saved to `destinationPath`. + +```typescript +const downloadedBytes = await NitroFS.downloadFile({ + url: 'https://example.com/files/document.pdf', + destinationPath: NitroFS.DOWNLOAD_DIR + '/document.pdf', + output: 'arrayBuffer', +}) + +if (!(downloadedBytes instanceof ArrayBuffer)) { + throw new Error('Expected ArrayBuffer') +} + +const view = new Uint8Array(downloadedBytes) +console.log('Downloaded byte length:', view.byteLength) +``` + ## 📝 Type Definitions ### `NitroFile` @@ -353,9 +376,16 @@ interface NitroDownloadOptions { url: string // Download endpoint URL destinationPath: string // Path where the downloaded file is saved headers?: Record // Custom headers + output?: 'file' | 'arrayBuffer' // Return file metadata or downloaded bytes } ``` +### `NitroDownloadResult` + +```typescript +type NitroDownloadResult = NitroFile | ArrayBuffer +``` + ### `NitroFileStat` ```typescript diff --git a/android/src/main/java/com/nitrofs/File+toMappedArrayBuffer.kt b/android/src/main/java/com/nitrofs/File+toMappedArrayBuffer.kt new file mode 100644 index 0000000..ba34829 --- /dev/null +++ b/android/src/main/java/com/nitrofs/File+toMappedArrayBuffer.kt @@ -0,0 +1,26 @@ +package com.nitrofs + +import com.margelo.nitro.core.ArrayBuffer +import java.io.File +import java.io.RandomAccessFile +import java.nio.channels.FileChannel + +internal fun File.toMappedArrayBuffer(): ArrayBuffer { + RandomAccessFile(this, "rw").use { randomAccessFile -> + val channel = randomAccessFile.channel + val byteSize = channel.size() + + if (byteSize > Int.MAX_VALUE) { + throw IllegalStateException( + "File is too large to expose as ArrayBuffer. path=$absolutePath, size=$byteSize" + ) + } + + if (byteSize == 0L) { + return ArrayBuffer.allocate(0) + } + + val mappedBuffer = channel.map(FileChannel.MapMode.PRIVATE, 0, byteSize) + return ArrayBuffer.wrap(mappedBuffer) + } +} diff --git a/android/src/main/java/com/nitrofs/FileDownloader.kt b/android/src/main/java/com/nitrofs/FileDownloader.kt index 312a8f5..a44d603 100644 --- a/android/src/main/java/com/nitrofs/FileDownloader.kt +++ b/android/src/main/java/com/nitrofs/FileDownloader.kt @@ -2,6 +2,8 @@ package com.nitrofs import android.util.Log import com.margelo.nitro.nitrofs.NitroDownloadOptions +import com.margelo.nitro.nitrofs.NitroDownloadOutput +import com.margelo.nitro.nitrofs.NitroDownloadResult import com.margelo.nitro.nitrofs.NitroFile import io.ktor.client.HttpClient import io.ktor.client.call.body @@ -22,7 +24,7 @@ class FileDownloader { suspend fun downloadFile( downloadOptions: NitroDownloadOptions, onProgress: ((Double, Double) -> Unit)? - ): NitroFile? { + ): NitroDownloadResult { var contentType = "" val outputFile = File(downloadOptions.destinationPath) outputFile.parentFile?.mkdirs() @@ -30,18 +32,17 @@ class FileDownloader { val client = HttpClient(OkHttp) - client.use { it - it.prepareGet(downloadOptions.url) { + client.use { httpClient -> + httpClient.prepareGet(downloadOptions.url) { method = HttpMethod.Get downloadOptions.headers?.forEach { (name, value) -> header(name, value) } onDownload { totalBytesSent, contentLength -> - if (totalBytesSent > 0 && contentLength != null){ - onProgress?.let { - withContext(Dispatchers.Main) { - onProgress.invoke(totalBytesSent.toDouble(), contentLength.toDouble()) - } + val progressCallback = onProgress + if (totalBytesSent > 0 && contentLength != null && progressCallback != null) { + withContext(Dispatchers.Main) { + progressCallback.invoke(totalBytesSent.toDouble(), contentLength.toDouble()) } } } @@ -56,10 +57,16 @@ class FileDownloader { } } - return NitroFile( - name = outputFile.name, - path = outputFile.absolutePath, - mimeType = contentType - ) + return when (downloadOptions.output) { + NitroDownloadOutput.ARRAYBUFFER -> NitroDownloadResult.First(outputFile.toMappedArrayBuffer()) + NitroDownloadOutput.FILE, + null -> NitroDownloadResult.Second( + NitroFile( + name = outputFile.name, + path = outputFile.absolutePath, + mimeType = contentType + ) + ) + } } } diff --git a/android/src/main/java/com/nitrofs/HybridNitroFS.kt b/android/src/main/java/com/nitrofs/HybridNitroFS.kt index a0c1be7..ca9887b 100755 --- a/android/src/main/java/com/nitrofs/HybridNitroFS.kt +++ b/android/src/main/java/com/nitrofs/HybridNitroFS.kt @@ -5,6 +5,7 @@ import com.margelo.nitro.NitroModules import com.margelo.nitro.core.Promise import com.margelo.nitro.nitrofs.HybridNitroFSSpec import com.margelo.nitro.nitrofs.NitroDownloadOptions +import com.margelo.nitro.nitrofs.NitroDownloadResult import com.margelo.nitro.nitrofs.NitroFile import com.margelo.nitro.nitrofs.NitroFileEncoding import com.margelo.nitro.nitrofs.NitroFileStat @@ -194,7 +195,7 @@ class HybridNitroFS: HybridNitroFSSpec() { override fun downloadFile( downloadOptions: NitroDownloadOptions, onProgress: ((Double, Double) -> Unit)? - ): Promise { + ): Promise { return Promise.async(ioScope) { try { nitroFsImpl.downloadFile(downloadOptions, onProgress) diff --git a/android/src/main/java/com/nitrofs/NitroFSImpl.kt b/android/src/main/java/com/nitrofs/NitroFSImpl.kt index 3cc7fed..db6bbc1 100644 --- a/android/src/main/java/com/nitrofs/NitroFSImpl.kt +++ b/android/src/main/java/com/nitrofs/NitroFSImpl.kt @@ -8,6 +8,7 @@ import android.util.Log import android.webkit.MimeTypeMap import com.facebook.react.bridge.ReactApplicationContext import com.margelo.nitro.nitrofs.NitroDownloadOptions +import com.margelo.nitro.nitrofs.NitroDownloadResult import com.margelo.nitro.nitrofs.NitroFile import com.margelo.nitro.nitrofs.NitroFileEncoding import com.margelo.nitro.nitrofs.NitroFileStat @@ -345,16 +346,11 @@ class NitroFSImpl(val context: ReactApplicationContext) { suspend fun downloadFile( downloadOptions: NitroDownloadOptions, onProgress: ((Double, Double) -> Unit)? - ): NitroFile { - val file = fileDownloader.downloadFile( + ): NitroDownloadResult { + return fileDownloader.downloadFile( downloadOptions, onProgress ) - if (file != null) { - return file - } else { - throw RuntimeException("Failed to download file from: ${downloadOptions.url}") - } } fun getFileEncoding(encoding: NitroFileEncoding): Charset { diff --git a/example/src/hooks/use-file-system.ts b/example/src/hooks/use-file-system.ts index 68aaaec..49f4b66 100644 --- a/example/src/hooks/use-file-system.ts +++ b/example/src/hooks/use-file-system.ts @@ -210,7 +210,7 @@ export const useFileSystem = () => { const url = 'https://httpbin.org/bytes/1024'; const destinationPath = `${NitroFS.DOWNLOAD_DIR}/downloaded_file.txt`; - const file = await NitroFS.downloadFile( + const result = await NitroFS.downloadFile( { url, destinationPath }, (downloadedBytes, totalBytes) => { const progress = (downloadedBytes / totalBytes) * 100; @@ -218,6 +218,11 @@ export const useFileSystem = () => { }, ); + if (result instanceof ArrayBuffer) { + throw new Error('Expected NitroFile result for default download output'); + } + + const file = result; Alert.alert('Success', `File downloaded successfully: ${file.name}`); setDownloadProgress(0); await listFiles(currentPath); diff --git a/ios/ArrayBuffer+mapFile.swift b/ios/ArrayBuffer+mapFile.swift new file mode 100644 index 0000000..a9bf5d4 --- /dev/null +++ b/ios/ArrayBuffer+mapFile.swift @@ -0,0 +1,41 @@ +import Darwin +import Foundation +import NitroModules + +extension ArrayBuffer { + static func mapFile(atPath path: String) throws -> ArrayBuffer { + let fileDescriptor = open(path, O_RDWR) + guard fileDescriptor >= 0 else { + throw NitroFSError.fileError(message: "Failed to open file for memory mapping. path=\(path), errno=\(errno)") + } + defer { + close(fileDescriptor) + } + + var fileStat = stat() + guard fstat(fileDescriptor, &fileStat) == 0 else { + throw NitroFSError.fileError(message: "Failed to stat file for memory mapping. path=\(path), errno=\(errno)") + } + + let byteSize = Int(fileStat.st_size) + guard byteSize >= 0 else { + throw NitroFSError.fileError(message: "Invalid file size for memory mapping. path=\(path), size=\(fileStat.st_size)") + } + + if byteSize == 0 { + return ArrayBuffer.allocate(size: 0) + } + + let mappedData = mmap(nil, byteSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fileDescriptor, 0) + guard mappedData != MAP_FAILED else { + throw NitroFSError.fileError(message: "Failed to memory map file. path=\(path), size=\(byteSize), errno=\(errno)") + } + guard let mappedData else { + throw NitroFSError.fileError(message: "Memory mapping returned nil. path=\(path), size=\(byteSize)") + } + + return ArrayBuffer.wrap(dataWithoutCopy: mappedData, size: byteSize) { + munmap(mappedData, byteSize) + } + } +} diff --git a/ios/HybridNitroFs.swift b/ios/HybridNitroFs.swift index b2116da..43b0942 100755 --- a/ios/HybridNitroFs.swift +++ b/ios/HybridNitroFs.swift @@ -61,7 +61,7 @@ class HybridNitroFS: HybridNitroFSSpec { } } - func copy(srcPath: String, destPath: String) throws -> NitroModules.Promise { + func copy(srcPath: String, destPath: String) throws -> Promise { return .async { [unowned self] in do { try self.nitroFSImpl.copy(source: srcPath, destination: destPath) @@ -72,7 +72,7 @@ class HybridNitroFS: HybridNitroFSSpec { } } - func unlink(path: String) throws -> NitroModules.Promise { + func unlink(path: String) throws -> Promise { return .async { [unowned self] in do { try self.nitroFSImpl.unlink(path: path) @@ -84,7 +84,7 @@ class HybridNitroFS: HybridNitroFSSpec { } } - func mkdir(path: String) throws -> NitroModules.Promise { + func mkdir(path: String) throws -> Promise { return .async { [unowned self] in do { try self.nitroFSImpl.mkdir(path: path) @@ -96,7 +96,7 @@ class HybridNitroFS: HybridNitroFSSpec { } } - func stat(path: String) throws -> NitroModules.Promise { + func stat(path: String) throws -> Promise { return .async { [unowned self] in do { return try self.nitroFSImpl.stat(path: path) @@ -107,7 +107,7 @@ class HybridNitroFS: HybridNitroFSSpec { } } - func readdir(path: String) throws -> NitroModules.Promise<[NitroFile]> { + func readdir(path: String) throws -> Promise<[NitroFile]> { return .async { do { return try self.nitroFSImpl.readdir(atPath: path) @@ -118,7 +118,7 @@ class HybridNitroFS: HybridNitroFSSpec { } } - func rename(oldPath: String, newPath: String) throws -> NitroModules.Promise { + func rename(oldPath: String, newPath: String) throws -> Promise { return .async { do { return try self.nitroFSImpl.rename(oldPath: oldPath, newPath: newPath) @@ -173,7 +173,7 @@ class HybridNitroFS: HybridNitroFSSpec { } } - func downloadFile(downloadOptions: NitroDownloadOptions, onProgress: ((Double, Double) -> Void)?) throws -> NitroModules.Promise { + func downloadFile(downloadOptions: NitroDownloadOptions, onProgress: ((Double, Double) -> Void)?) throws -> Promise { return .async { [unowned self] in do { return try await self.nitroFSImpl.downloadFile( diff --git a/ios/NitroFSFileDownloader.swift b/ios/NitroFSFileDownloader.swift index 613737c..f9633b4 100644 --- a/ios/NitroFSFileDownloader.swift +++ b/ios/NitroFSFileDownloader.swift @@ -6,55 +6,58 @@ // import Foundation +import NitroModules final class NitroFSFileDownloader: NSObject { private weak var fileManager: FileManager? private var downloadTask: URLSessionDownloadTask? private var onProgress: ((Double, Double) -> Void)? - private var continuation: CheckedContinuation? + private var continuation: CheckedContinuation? private var destinationPath: String? - + private var downloadOutput: NitroDownloadOutput? + init(fileManager: FileManager) { self.fileManager = fileManager super.init() } - + func downloadFile( _ downloadOptions: NitroDownloadOptions, onProgress: ((Double, Double) -> Void)? - ) async throws -> NitroFile { + ) async throws -> NitroDownloadResult { guard fileManager != nil else { throw NitroFSError.unavailable(message: "FileManager is not available") } - + self.onProgress = onProgress self.destinationPath = downloadOptions.destinationPath - + self.downloadOutput = downloadOptions.output + let request = try makeRequest( url: downloadOptions.url, headers: downloadOptions.headers ) - + let session: URLSession = { let config = URLSessionConfiguration.default config.requestCachePolicy = .reloadIgnoringLocalCacheData return URLSession(configuration: config, delegate: self, delegateQueue: .main) }() - - + + return try await withCheckedThrowingContinuation { continuation in self.continuation = continuation downloadTask = session.downloadTask(with: request) downloadTask?.resume() } } - + func cancelDownload() { downloadTask?.cancel() } - + // MARK: - Private Methods - + private func makeRequest( url: String, headers: [String: String]? @@ -63,7 +66,7 @@ final class NitroFSFileDownloader: NSObject { let url = URL(string: encoded) else { throw URLError(.badURL) } - + var request = URLRequest(url: url) request.httpMethod = "GET" request.cachePolicy = .reloadIgnoringLocalCacheData @@ -72,43 +75,49 @@ final class NitroFSFileDownloader: NSObject { } return request } - + private func handleDownloadCompletion( location: URL, response: URLResponse, downloadTask: URLSessionDownloadTask - ) throws -> NitroFile { + ) throws -> NitroDownloadResult { guard let fileManager else { throw NitroFSError.unavailable(message: "FileManager is not available") } - + guard let response = response as? HTTPURLResponse else { throw NitroFSError.networkError(message: "Invalid response type") } - + guard (200...299).contains(response.statusCode) else { throw NitroFSError.networkError(message: "HTTP Error: \(response.statusCode)") } - + guard let destinationPath = self.destinationPath else { throw NitroFSError.networkError(message: "Destination path not set") } - + let destinationURL = URL(fileURLWithPath: destinationPath) - + try fileManager.createDirectory(at: destinationURL.deletingLastPathComponent(), withIntermediateDirectories: true) - + if fileManager.fileExists(atPath: destinationPath) { try fileManager.removeItem(at: destinationURL) } - + try fileManager.moveItem(at: location, to: destinationURL) - - return NitroFile( + + let file = NitroFile( name: destinationURL.lastPathComponent, mimeType: response.allHeaderFields["Content-Type"] as? String ?? "application/octet-stream", path: destinationPath ) + + if downloadOutput == .arraybuffer { + return .first(try ArrayBuffer.mapFile(atPath: destinationPath)) + } + + return .second(file) } } @@ -121,7 +130,7 @@ extension NitroFSFileDownloader: URLSessionDownloadDelegate { didFinishDownloadingTo location: URL ) { guard let continuation = self.continuation else { return } - + do { let file = try handleDownloadCompletion( location: location, @@ -135,7 +144,7 @@ extension NitroFSFileDownloader: URLSessionDownloadDelegate { self.continuation = nil session.finishTasksAndInvalidate() } - + func urlSession( _ session: URLSession, downloadTask: URLSessionDownloadTask, @@ -148,7 +157,7 @@ extension NitroFSFileDownloader: URLSessionDownloadDelegate { self?.onProgress?(Double(totalBytesWritten), Double(totalBytesExpectedToWrite)) } } - + func urlSession( _ session: URLSession, task: URLSessionTask, diff --git a/ios/NitroFSImpl.swift b/ios/NitroFSImpl.swift index 9bccc98..27d0415 100644 --- a/ios/NitroFSImpl.swift +++ b/ios/NitroFSImpl.swift @@ -205,7 +205,7 @@ class NitroFSImpl { func downloadFile( downloadOptions: NitroDownloadOptions, onProgress: ((Double, Double) -> Void)? - ) async throws -> NitroFile { + ) async throws -> NitroDownloadResult { guard let fileManager else { throw NitroFSError.unavailable(message: "Failed to download file. FileManager is unavailable") } diff --git a/nitrogen/generated/android/NitroFS+autolinking.cmake b/nitrogen/generated/android/NitroFS+autolinking.cmake index 76ad8e8..073fcca 100644 --- a/nitrogen/generated/android/NitroFS+autolinking.cmake +++ b/nitrogen/generated/android/NitroFS+autolinking.cmake @@ -36,6 +36,7 @@ target_sources( ../nitrogen/generated/shared/c++/HybridNitroFSSpec.cpp # Android-specific Nitrogen C++ sources ../nitrogen/generated/android/c++/JHybridNitroFSSpec.cpp + ../nitrogen/generated/android/c++/JNitroDownloadResult.cpp ) # From node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake diff --git a/nitrogen/generated/android/c++/JHybridNitroFSSpec.cpp b/nitrogen/generated/android/c++/JHybridNitroFSSpec.cpp index 0b1b71d..e2d080a 100644 --- a/nitrogen/generated/android/c++/JHybridNitroFSSpec.cpp +++ b/nitrogen/generated/android/c++/JHybridNitroFSSpec.cpp @@ -19,6 +19,8 @@ namespace margelo::nitro::nitrofs { struct NitroUploadOptions; } namespace margelo::nitro::nitrofs { enum class NitroUploadMethod; } // Forward declaration of `NitroDownloadOptions` to properly resolve imports. namespace margelo::nitro::nitrofs { struct NitroDownloadOptions; } +// Forward declaration of `NitroDownloadOutput` to properly resolve imports. +namespace margelo::nitro::nitrofs { enum class NitroDownloadOutput; } #include #include @@ -29,6 +31,10 @@ namespace margelo::nitro::nitrofs { struct NitroDownloadOptions; } #include "NitroFile.hpp" #include #include "JNitroFile.hpp" +#include +#include +#include "JNitroDownloadResult.hpp" +#include #include "NitroFileEncoding.hpp" #include "JNitroFileEncoding.hpp" #include "NitroUploadOptions.hpp" @@ -42,6 +48,8 @@ namespace margelo::nitro::nitrofs { struct NitroDownloadOptions; } #include #include "NitroDownloadOptions.hpp" #include "JNitroDownloadOptions.hpp" +#include "NitroDownloadOutput.hpp" +#include "JNitroDownloadOutput.hpp" namespace margelo::nitro::nitrofs { @@ -310,13 +318,13 @@ namespace margelo::nitro::nitrofs { return __promise; }(); } - std::shared_ptr> JHybridNitroFSSpec::downloadFile(const NitroDownloadOptions& downloadOptions, const std::optional>& onProgress) { + std::shared_ptr, NitroFile>>> JHybridNitroFSSpec::downloadFile(const NitroDownloadOptions& downloadOptions, const std::optional>& onProgress) { static const auto method = _javaPart->javaClassStatic()->getMethod(jni::alias_ref /* downloadOptions */, jni::alias_ref /* onProgress */)>("downloadFile_cxx"); auto __result = method(_javaPart, JNitroDownloadOptions::fromCpp(downloadOptions), onProgress.has_value() ? JFunc_void_double_double_cxx::fromCpp(onProgress.value()) : nullptr); return [&]() { - auto __promise = Promise::create(); + auto __promise = Promise, NitroFile>>::create(); __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& __boxedResult) { - auto __result = jni::static_ref_cast(__boxedResult); + auto __result = jni::static_ref_cast(__boxedResult); __promise->resolve(__result->toCpp()); }); __result->cthis()->addOnRejectedListener([=](const jni::alias_ref& __throwable) { diff --git a/nitrogen/generated/android/c++/JHybridNitroFSSpec.hpp b/nitrogen/generated/android/c++/JHybridNitroFSSpec.hpp index ad88310..cfaa079 100644 --- a/nitrogen/generated/android/c++/JHybridNitroFSSpec.hpp +++ b/nitrogen/generated/android/c++/JHybridNitroFSSpec.hpp @@ -75,7 +75,7 @@ namespace margelo::nitro::nitrofs { std::string basename(const std::string& path) override; std::string extname(const std::string& path) override; std::shared_ptr> uploadFile(const NitroUploadOptions& uploadOptions, const std::optional>& onProgress) override; - std::shared_ptr> downloadFile(const NitroDownloadOptions& downloadOptions, const std::optional>& onProgress) override; + std::shared_ptr, NitroFile>>> downloadFile(const NitroDownloadOptions& downloadOptions, const std::optional>& onProgress) override; private: jni::global_ref _javaPart; diff --git a/nitrogen/generated/android/c++/JNitroDownloadOptions.hpp b/nitrogen/generated/android/c++/JNitroDownloadOptions.hpp index 8f6a7a9..3dbeb47 100644 --- a/nitrogen/generated/android/c++/JNitroDownloadOptions.hpp +++ b/nitrogen/generated/android/c++/JNitroDownloadOptions.hpp @@ -10,6 +10,8 @@ #include #include "NitroDownloadOptions.hpp" +#include "JNitroDownloadOutput.hpp" +#include "NitroDownloadOutput.hpp" #include #include #include @@ -39,6 +41,8 @@ namespace margelo::nitro::nitrofs { jni::local_ref destinationPath = this->getFieldValue(fieldDestinationPath); static const auto fieldHeaders = clazz->getField>("headers"); jni::local_ref> headers = this->getFieldValue(fieldHeaders); + static const auto fieldOutput = clazz->getField("output"); + jni::local_ref output = this->getFieldValue(fieldOutput); return NitroDownloadOptions( url->toStdString(), destinationPath->toStdString(), @@ -49,7 +53,8 @@ namespace margelo::nitro::nitrofs { __map.emplace(__entry.first->toStdString(), __entry.second->toStdString()); } return __map; - }()) : std::nullopt + }()) : std::nullopt, + output != nullptr ? std::make_optional(output->toCpp()) : std::nullopt ); } @@ -59,7 +64,7 @@ namespace margelo::nitro::nitrofs { */ [[maybe_unused]] static jni::local_ref fromCpp(const NitroDownloadOptions& value) { - using JSignature = JNitroDownloadOptions(jni::alias_ref, jni::alias_ref, jni::alias_ref>); + using JSignature = JNitroDownloadOptions(jni::alias_ref, jni::alias_ref, jni::alias_ref>, jni::alias_ref); static const auto clazz = javaClassStatic(); static const auto create = clazz->getStaticMethod("fromCpp"); return create( @@ -72,7 +77,8 @@ namespace margelo::nitro::nitrofs { __map->put(jni::make_jstring(__entry.first), jni::make_jstring(__entry.second)); } return __map; - }() : nullptr + }() : nullptr, + value.output.has_value() ? JNitroDownloadOutput::fromCpp(value.output.value()) : nullptr ); } }; diff --git a/nitrogen/generated/android/c++/JNitroDownloadOutput.hpp b/nitrogen/generated/android/c++/JNitroDownloadOutput.hpp new file mode 100644 index 0000000..f6c35a3 --- /dev/null +++ b/nitrogen/generated/android/c++/JNitroDownloadOutput.hpp @@ -0,0 +1,58 @@ +/// +/// JNitroDownloadOutput.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "NitroDownloadOutput.hpp" + +namespace margelo::nitro::nitrofs { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "NitroDownloadOutput" and the the Kotlin enum "NitroDownloadOutput". + */ + struct JNitroDownloadOutput final: public jni::JavaClass { + public: + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/nitrofs/NitroDownloadOutput;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum NitroDownloadOutput. + */ + [[maybe_unused]] + [[nodiscard]] + NitroDownloadOutput toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldOrdinal = clazz->getField("value"); + int ordinal = this->getFieldValue(fieldOrdinal); + return static_cast(ordinal); + } + + public: + /** + * Create a Java/Kotlin-based enum with the given C++ enum's value. + */ + [[maybe_unused]] + static jni::alias_ref fromCpp(NitroDownloadOutput value) { + static const auto clazz = javaClassStatic(); + switch (value) { + case NitroDownloadOutput::FILE: + static const auto fieldFILE = clazz->getStaticField("FILE"); + return clazz->getStaticFieldValue(fieldFILE); + case NitroDownloadOutput::ARRAYBUFFER: + static const auto fieldARRAYBUFFER = clazz->getStaticField("ARRAYBUFFER"); + return clazz->getStaticFieldValue(fieldARRAYBUFFER); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::nitrofs diff --git a/nitrogen/generated/android/c++/JNitroDownloadResult.cpp b/nitrogen/generated/android/c++/JNitroDownloadResult.cpp new file mode 100644 index 0000000..8e23993 --- /dev/null +++ b/nitrogen/generated/android/c++/JNitroDownloadResult.cpp @@ -0,0 +1,26 @@ +/// +/// JNitroDownloadResult.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include "JNitroDownloadResult.hpp" + +namespace margelo::nitro::nitrofs { + /** + * Converts JNitroDownloadResult to std::variant, NitroFile> + */ + std::variant, NitroFile> JNitroDownloadResult::toCpp() const { + if (isInstanceOf(JNitroDownloadResult_impl::First::javaClassStatic())) { + // It's a `std::shared_ptr` + auto jniValue = static_cast(this)->getValue(); + return jniValue->cthis()->getArrayBuffer(); + } else if (isInstanceOf(JNitroDownloadResult_impl::Second::javaClassStatic())) { + // It's a `NitroFile` + auto jniValue = static_cast(this)->getValue(); + return jniValue->toCpp(); + } + throw std::invalid_argument("Variant is unknown Kotlin instance!"); + } +} // namespace margelo::nitro::nitrofs diff --git a/nitrogen/generated/android/c++/JNitroDownloadResult.hpp b/nitrogen/generated/android/c++/JNitroDownloadResult.hpp new file mode 100644 index 0000000..5c37997 --- /dev/null +++ b/nitrogen/generated/android/c++/JNitroDownloadResult.hpp @@ -0,0 +1,72 @@ +/// +/// JNitroDownloadResult.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include +#include "NitroFile.hpp" +#include +#include +#include "JNitroFile.hpp" +#include + +namespace margelo::nitro::nitrofs { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ std::variant and the Java class "NitroDownloadResult". + */ + class JNitroDownloadResult: public jni::JavaClass { + public: + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/nitrofs/NitroDownloadResult;"; + + static jni::local_ref create_0(jni::alias_ref value) { + static const auto method = javaClassStatic()->getStaticMethod)>("create"); + return method(javaClassStatic(), value); + } + static jni::local_ref create_1(jni::alias_ref value) { + static const auto method = javaClassStatic()->getStaticMethod)>("create"); + return method(javaClassStatic(), value); + } + + static jni::local_ref fromCpp(const std::variant, NitroFile>& variant) { + switch (variant.index()) { + case 0: return create_0(JArrayBuffer::wrap(std::get<0>(variant))); + case 1: return create_1(JNitroFile::fromCpp(std::get<1>(variant))); + default: throw std::invalid_argument("Variant holds unknown index! (" + std::to_string(variant.index()) + ")"); + } + } + + [[nodiscard]] std::variant, NitroFile> toCpp() const; + }; + + namespace JNitroDownloadResult_impl { + class First final: public jni::JavaClass { + public: + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/nitrofs/NitroDownloadResult$First;"; + + [[nodiscard]] jni::local_ref getValue() const { + static const auto field = javaClassStatic()->getField("value"); + return getFieldValue(field); + } + }; + + class Second final: public jni::JavaClass { + public: + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/nitrofs/NitroDownloadResult$Second;"; + + [[nodiscard]] jni::local_ref getValue() const { + static const auto field = javaClassStatic()->getField("value"); + return getFieldValue(field); + } + }; + } // namespace JNitroDownloadResult_impl +} // namespace margelo::nitro::nitrofs diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/HybridNitroFSSpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/HybridNitroFSSpec.kt index 97a56d8..5d6bab0 100644 --- a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/HybridNitroFSSpec.kt +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/HybridNitroFSSpec.kt @@ -11,6 +11,7 @@ import androidx.annotation.Keep import com.facebook.jni.HybridData import com.facebook.proguard.annotations.DoNotStrip import com.margelo.nitro.core.Promise +import com.margelo.nitro.core.ArrayBuffer import com.margelo.nitro.core.HybridObject /** @@ -120,11 +121,11 @@ abstract class HybridNitroFSSpec: HybridObject() { return __result } - abstract fun downloadFile(downloadOptions: NitroDownloadOptions, onProgress: ((downloadedBytes: Double, totalBytes: Double) -> Unit)?): Promise + abstract fun downloadFile(downloadOptions: NitroDownloadOptions, onProgress: ((downloadedBytes: Double, totalBytes: Double) -> Unit)?): Promise @DoNotStrip @Keep - private fun downloadFile_cxx(downloadOptions: NitroDownloadOptions, onProgress: Func_void_double_double?): Promise { + private fun downloadFile_cxx(downloadOptions: NitroDownloadOptions, onProgress: Func_void_double_double?): Promise { val __result = downloadFile(downloadOptions, onProgress?.let { it }) return __result } diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/NitroDownloadOptions.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/NitroDownloadOptions.kt index b543dc7..f5025c1 100644 --- a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/NitroDownloadOptions.kt +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/NitroDownloadOptions.kt @@ -26,7 +26,10 @@ data class NitroDownloadOptions( val destinationPath: String, @DoNotStrip @Keep - val headers: Map? + val headers: Map?, + @DoNotStrip + @Keep + val output: NitroDownloadOutput? ) { /* primary constructor */ @@ -36,13 +39,15 @@ data class NitroDownloadOptions( return Objects.deepEquals(this.url, other.url) && Objects.deepEquals(this.destinationPath, other.destinationPath) && Objects.deepEquals(this.headers, other.headers) + && Objects.deepEquals(this.output, other.output) } override fun hashCode(): Int { return arrayOf( url, destinationPath, - headers + headers, + output ).contentDeepHashCode() } @@ -54,8 +59,8 @@ data class NitroDownloadOptions( @Keep @Suppress("unused") @JvmStatic - private fun fromCpp(url: String, destinationPath: String, headers: Map?): NitroDownloadOptions { - return NitroDownloadOptions(url, destinationPath, headers) + private fun fromCpp(url: String, destinationPath: String, headers: Map?, output: NitroDownloadOutput?): NitroDownloadOptions { + return NitroDownloadOptions(url, destinationPath, headers, output) } } } diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/NitroDownloadOutput.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/NitroDownloadOutput.kt new file mode 100644 index 0000000..736ed5c --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/NitroDownloadOutput.kt @@ -0,0 +1,23 @@ +/// +/// NitroDownloadOutput.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.nitrofs + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "NitroDownloadOutput". + */ +@DoNotStrip +@Keep +enum class NitroDownloadOutput(@DoNotStrip @Keep val value: Int) { + FILE(0), + ARRAYBUFFER(1); + + companion object +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/NitroDownloadResult.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/NitroDownloadResult.kt new file mode 100644 index 0000000..863dfb2 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/NitroDownloadResult.kt @@ -0,0 +1,62 @@ +/// +/// NitroDownloadResult.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.nitrofs + +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.ArrayBuffer + +/** + * Represents the TypeScript variant "ArrayBuffer | NitroFile". + */ +@Suppress("ClassName") +@DoNotStrip +sealed class NitroDownloadResult { + @DoNotStrip + data class First(@DoNotStrip val value: ArrayBuffer): NitroDownloadResult() + @DoNotStrip + data class Second(@DoNotStrip val value: NitroFile): NitroDownloadResult() + + inline fun asType(): T? { + return when (this) { + is First -> (value) as? T + is Second -> (value) as? T + } + } + inline fun isType(): Boolean { + return asType() != null + } + inline fun match(first: (ArrayBuffer) -> R, second: (NitroFile) -> R): R { + return when (this) { + is First -> first(value) + is Second -> second(value) + } + } + + val isFirst: Boolean + get() = this is First + val isSecond: Boolean + get() = this is Second + + fun asFirstOrNull(): ArrayBuffer? { + val value = (this as? First)?.value ?: return null + return value + } + fun asSecondOrNull(): NitroFile? { + val value = (this as? Second)?.value ?: return null + return value + } + + companion object { + @JvmStatic + @DoNotStrip + fun create(value: ArrayBuffer): NitroDownloadResult = First(value) + @JvmStatic + @DoNotStrip + fun create(value: NitroFile): NitroDownloadResult = Second(value) + } +} diff --git a/nitrogen/generated/ios/NitroFS-Swift-Cxx-Bridge.cpp b/nitrogen/generated/ios/NitroFS-Swift-Cxx-Bridge.cpp index aad784e..2ca1f1a 100644 --- a/nitrogen/generated/ios/NitroFS-Swift-Cxx-Bridge.cpp +++ b/nitrogen/generated/ios/NitroFS-Swift-Cxx-Bridge.cpp @@ -70,10 +70,10 @@ namespace margelo::nitro::nitrofs::bridge::swift { }; } - // pragma MARK: std::function - Func_void_NitroFile create_Func_void_NitroFile(void* NON_NULL swiftClosureWrapper) noexcept { - auto swiftClosure = NitroFS::Func_void_NitroFile::fromUnsafe(swiftClosureWrapper); - return [swiftClosure = std::move(swiftClosure)](const NitroFile& result) mutable -> void { + // pragma MARK: std::function, NitroFile>& /* result */)> + Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_ create_Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = NitroFS::Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const std::variant, NitroFile>& result) mutable -> void { swiftClosure.call(result); }; } diff --git a/nitrogen/generated/ios/NitroFS-Swift-Cxx-Bridge.hpp b/nitrogen/generated/ios/NitroFS-Swift-Cxx-Bridge.hpp index 30b0fee..72930d8 100644 --- a/nitrogen/generated/ios/NitroFS-Swift-Cxx-Bridge.hpp +++ b/nitrogen/generated/ios/NitroFS-Swift-Cxx-Bridge.hpp @@ -8,8 +8,12 @@ #pragma once // Forward declarations of C++ defined types +// Forward declaration of `ArrayBufferHolder` to properly resolve imports. +namespace NitroModules { class ArrayBufferHolder; } // Forward declaration of `HybridNitroFSSpec` to properly resolve imports. namespace margelo::nitro::nitrofs { class HybridNitroFSSpec; } +// Forward declaration of `NitroDownloadOutput` to properly resolve imports. +namespace margelo::nitro::nitrofs { enum class NitroDownloadOutput; } // Forward declaration of `NitroFileStat` to properly resolve imports. namespace margelo::nitro::nitrofs { struct NitroFileStat; } // Forward declaration of `NitroFile` to properly resolve imports. @@ -23,9 +27,12 @@ namespace NitroFS { class HybridNitroFSSpec_cxx; } // Include C++ defined types #include "HybridNitroFSSpec.hpp" +#include "NitroDownloadOutput.hpp" #include "NitroFile.hpp" #include "NitroFileStat.hpp" #include "NitroUploadMethod.hpp" +#include +#include #include #include #include @@ -35,6 +42,7 @@ namespace NitroFS { class HybridNitroFSSpec_cxx; } #include #include #include +#include #include /** @@ -54,7 +62,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline PromiseHolder wrap_std__shared_ptr_Promise_bool__(std::shared_ptr> promise) noexcept { return PromiseHolder(std::move(promise)); } - + // pragma MARK: std::function /** * Specialized version of `std::function`. @@ -76,7 +84,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Func_void_bool_Wrapper wrap_Func_void_bool(Func_void_bool value) noexcept { return Func_void_bool_Wrapper(std::move(value)); } - + // pragma MARK: std::function /** * Specialized version of `std::function`. @@ -98,7 +106,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Func_void_std__exception_ptr_Wrapper wrap_Func_void_std__exception_ptr(Func_void_std__exception_ptr value) noexcept { return Func_void_std__exception_ptr_Wrapper(std::move(value)); } - + // pragma MARK: std::shared_ptr> /** * Specialized version of `std::shared_ptr>`. @@ -110,7 +118,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline PromiseHolder wrap_std__shared_ptr_Promise_void__(std::shared_ptr> promise) noexcept { return PromiseHolder(std::move(promise)); } - + // pragma MARK: std::function /** * Specialized version of `std::function`. @@ -132,7 +140,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Func_void_Wrapper wrap_Func_void(Func_void value) noexcept { return Func_void_Wrapper(std::move(value)); } - + // pragma MARK: std::shared_ptr> /** * Specialized version of `std::shared_ptr>`. @@ -144,7 +152,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline PromiseHolder wrap_std__shared_ptr_Promise_std__string__(std::shared_ptr> promise) noexcept { return PromiseHolder(std::move(promise)); } - + // pragma MARK: std::function /** * Specialized version of `std::function`. @@ -166,7 +174,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Func_void_std__string_Wrapper wrap_Func_void_std__string(Func_void_std__string value) noexcept { return Func_void_std__string_Wrapper(std::move(value)); } - + // pragma MARK: std::shared_ptr> /** * Specialized version of `std::shared_ptr>`. @@ -178,7 +186,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline PromiseHolder wrap_std__shared_ptr_Promise_NitroFileStat__(std::shared_ptr> promise) noexcept { return PromiseHolder(std::move(promise)); } - + // pragma MARK: std::function /** * Specialized version of `std::function`. @@ -200,7 +208,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Func_void_NitroFileStat_Wrapper wrap_Func_void_NitroFileStat(Func_void_NitroFileStat value) noexcept { return Func_void_NitroFileStat_Wrapper(std::move(value)); } - + // pragma MARK: std::vector /** * Specialized version of `std::vector`. @@ -211,7 +219,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { vector.reserve(size); return vector; } - + // pragma MARK: std::shared_ptr>> /** * Specialized version of `std::shared_ptr>>`. @@ -223,7 +231,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline PromiseHolder> wrap_std__shared_ptr_Promise_std__vector_NitroFile___(std::shared_ptr>> promise) noexcept { return PromiseHolder>(std::move(promise)); } - + // pragma MARK: std::function& /* result */)> /** * Specialized version of `std::function&)>`. @@ -245,7 +253,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Func_void_std__vector_NitroFile__Wrapper wrap_Func_void_std__vector_NitroFile_(Func_void_std__vector_NitroFile_ value) noexcept { return Func_void_std__vector_NitroFile__Wrapper(std::move(value)); } - + // pragma MARK: std::optional /** * Specialized version of `std::optional`. @@ -260,7 +268,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline NitroUploadMethod get_std__optional_NitroUploadMethod_(const std::optional& optional) noexcept { return optional.value(); } - + // pragma MARK: std::optional /** * Specialized version of `std::optional`. @@ -275,7 +283,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline std::string get_std__optional_std__string_(const std::optional& optional) noexcept { return optional.value(); } - + // pragma MARK: std::unordered_map /** * Specialized version of `std::unordered_map`. @@ -300,7 +308,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline void emplace_std__unordered_map_std__string__std__string_(std__unordered_map_std__string__std__string_& map, const std::string& key, const std::string& value) noexcept { map.emplace(key, value); } - + // pragma MARK: std::optional> /** * Specialized version of `std::optional>`. @@ -315,7 +323,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline std::unordered_map get_std__optional_std__unordered_map_std__string__std__string__(const std::optional>& optional) noexcept { return optional.value(); } - + // pragma MARK: std::function /** * Specialized version of `std::function`. @@ -337,7 +345,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Func_void_double_double_Wrapper wrap_Func_void_double_double(Func_void_double_double value) noexcept { return Func_void_double_double_Wrapper(std::move(value)); } - + // pragma MARK: std::optional> /** * Specialized version of `std::optional>`. @@ -352,41 +360,85 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline std::function get_std__optional_std__function_void_double____uploadedBytes_____double____totalBytes______(const std::optional>& optional) noexcept { return optional.value(); } - - // pragma MARK: std::shared_ptr> + + // pragma MARK: std::variant, NitroFile> + /** + * Wrapper struct for `std::variant, NitroFile>`. + * std::variant cannot be used in Swift because of a Swift bug. + * Not even specializing it works. So we create a wrapper struct. + */ + struct std__variant_std__shared_ptr_ArrayBuffer___NitroFile_ final { + std::variant, NitroFile> variant; + std__variant_std__shared_ptr_ArrayBuffer___NitroFile_(std::variant, NitroFile> variant): variant(variant) { } + operator std::variant, NitroFile>() const noexcept { + return variant; + } + inline size_t index() const noexcept { + return variant.index(); + } + inline std::shared_ptr get_0() const noexcept { + return std::get<0>(variant); + } + inline NitroFile get_1() const noexcept { + return std::get<1>(variant); + } + }; + inline std__variant_std__shared_ptr_ArrayBuffer___NitroFile_ create_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_(const std::shared_ptr& value) noexcept { + return std__variant_std__shared_ptr_ArrayBuffer___NitroFile_(value); + } + inline std__variant_std__shared_ptr_ArrayBuffer___NitroFile_ create_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_(const NitroFile& value) noexcept { + return std__variant_std__shared_ptr_ArrayBuffer___NitroFile_(value); + } + + // pragma MARK: std::shared_ptr, NitroFile>>> /** - * Specialized version of `std::shared_ptr>`. + * Specialized version of `std::shared_ptr, NitroFile>>>`. */ - using std__shared_ptr_Promise_NitroFile__ = std::shared_ptr>; - inline std::shared_ptr> create_std__shared_ptr_Promise_NitroFile__() noexcept { - return Promise::create(); + using std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile___ = std::shared_ptr, NitroFile>>>; + inline std::shared_ptr, NitroFile>>> create_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile___() noexcept { + return Promise, NitroFile>>::create(); } - inline PromiseHolder wrap_std__shared_ptr_Promise_NitroFile__(std::shared_ptr> promise) noexcept { - return PromiseHolder(std::move(promise)); + inline PromiseHolder, NitroFile>> wrap_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile___(std::shared_ptr, NitroFile>>> promise) noexcept { + return PromiseHolder, NitroFile>>(std::move(promise)); } - - // pragma MARK: std::function + + // pragma MARK: std::function, NitroFile>& /* result */)> /** - * Specialized version of `std::function`. + * Specialized version of `std::function, NitroFile>&)>`. */ - using Func_void_NitroFile = std::function; + using Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_ = std::function, NitroFile>& /* result */)>; /** - * Wrapper class for a `std::function`, this can be used from Swift. + * Wrapper class for a `std::function, NitroFile>& / * result * /)>`, this can be used from Swift. */ - class Func_void_NitroFile_Wrapper final { + class Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile__Wrapper final { public: - explicit Func_void_NitroFile_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} - inline void call(NitroFile result) const noexcept { + explicit Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile__Wrapper(std::function, NitroFile>& /* result */)>&& func): _function(std::make_unique, NitroFile>& /* result */)>>(std::move(func))) {} + inline void call(std::variant, NitroFile> result) const noexcept { _function->operator()(result); } private: - std::unique_ptr> _function; + std::unique_ptr, NitroFile>& /* result */)>> _function; } SWIFT_NONCOPYABLE; - Func_void_NitroFile create_Func_void_NitroFile(void* NON_NULL swiftClosureWrapper) noexcept; - inline Func_void_NitroFile_Wrapper wrap_Func_void_NitroFile(Func_void_NitroFile value) noexcept { - return Func_void_NitroFile_Wrapper(std::move(value)); + Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_ create_Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile__Wrapper wrap_Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_(Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_ value) noexcept { + return Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile__Wrapper(std::move(value)); + } + + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_NitroDownloadOutput_ = std::optional; + inline std::optional create_std__optional_NitroDownloadOutput_(const NitroDownloadOutput& value) noexcept { + return std::optional(value); } - + inline bool has_value_std__optional_NitroDownloadOutput_(const std::optional& optional) noexcept { + return optional.has_value(); + } + inline NitroDownloadOutput get_std__optional_NitroDownloadOutput_(const std::optional& optional) noexcept { + return optional.value(); + } + // pragma MARK: std::optional> /** * Specialized version of `std::optional>`. @@ -401,7 +453,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline std::function get_std__optional_std__function_void_double____downloadedBytes_____double____totalBytes______(const std::optional>& optional) noexcept { return optional.value(); } - + // pragma MARK: std::shared_ptr /** * Specialized version of `std::shared_ptr`. @@ -409,11 +461,11 @@ namespace margelo::nitro::nitrofs::bridge::swift { using std__shared_ptr_HybridNitroFSSpec_ = std::shared_ptr; std::shared_ptr create_std__shared_ptr_HybridNitroFSSpec_(void* NON_NULL swiftUnsafePointer) noexcept; void* NON_NULL get_std__shared_ptr_HybridNitroFSSpec_(std__shared_ptr_HybridNitroFSSpec_ cppType); - + // pragma MARK: std::weak_ptr using std__weak_ptr_HybridNitroFSSpec_ = std::weak_ptr; inline std__weak_ptr_HybridNitroFSSpec_ weakify_std__shared_ptr_HybridNitroFSSpec_(const std::shared_ptr& strong) noexcept { return strong; } - + // pragma MARK: Result>> using Result_std__shared_ptr_Promise_bool___ = Result>>; inline Result_std__shared_ptr_Promise_bool___ create_Result_std__shared_ptr_Promise_bool___(const std::shared_ptr>& value) noexcept { @@ -422,7 +474,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Result_std__shared_ptr_Promise_bool___ create_Result_std__shared_ptr_Promise_bool___(const std::exception_ptr& error) noexcept { return Result>>::withError(error); } - + // pragma MARK: Result>> using Result_std__shared_ptr_Promise_void___ = Result>>; inline Result_std__shared_ptr_Promise_void___ create_Result_std__shared_ptr_Promise_void___(const std::shared_ptr>& value) noexcept { @@ -431,7 +483,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Result_std__shared_ptr_Promise_void___ create_Result_std__shared_ptr_Promise_void___(const std::exception_ptr& error) noexcept { return Result>>::withError(error); } - + // pragma MARK: Result>> using Result_std__shared_ptr_Promise_std__string___ = Result>>; inline Result_std__shared_ptr_Promise_std__string___ create_Result_std__shared_ptr_Promise_std__string___(const std::shared_ptr>& value) noexcept { @@ -440,7 +492,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Result_std__shared_ptr_Promise_std__string___ create_Result_std__shared_ptr_Promise_std__string___(const std::exception_ptr& error) noexcept { return Result>>::withError(error); } - + // pragma MARK: Result>> using Result_std__shared_ptr_Promise_NitroFileStat___ = Result>>; inline Result_std__shared_ptr_Promise_NitroFileStat___ create_Result_std__shared_ptr_Promise_NitroFileStat___(const std::shared_ptr>& value) noexcept { @@ -449,7 +501,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Result_std__shared_ptr_Promise_NitroFileStat___ create_Result_std__shared_ptr_Promise_NitroFileStat___(const std::exception_ptr& error) noexcept { return Result>>::withError(error); } - + // pragma MARK: Result>>> using Result_std__shared_ptr_Promise_std__vector_NitroFile____ = Result>>>; inline Result_std__shared_ptr_Promise_std__vector_NitroFile____ create_Result_std__shared_ptr_Promise_std__vector_NitroFile____(const std::shared_ptr>>& value) noexcept { @@ -458,7 +510,7 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Result_std__shared_ptr_Promise_std__vector_NitroFile____ create_Result_std__shared_ptr_Promise_std__vector_NitroFile____(const std::exception_ptr& error) noexcept { return Result>>>::withError(error); } - + // pragma MARK: Result using Result_std__string_ = Result; inline Result_std__string_ create_Result_std__string_(const std::string& value) noexcept { @@ -467,14 +519,14 @@ namespace margelo::nitro::nitrofs::bridge::swift { inline Result_std__string_ create_Result_std__string_(const std::exception_ptr& error) noexcept { return Result::withError(error); } - - // pragma MARK: Result>> - using Result_std__shared_ptr_Promise_NitroFile___ = Result>>; - inline Result_std__shared_ptr_Promise_NitroFile___ create_Result_std__shared_ptr_Promise_NitroFile___(const std::shared_ptr>& value) noexcept { - return Result>>::withValue(value); + + // pragma MARK: Result, NitroFile>>>> + using Result_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile____ = Result, NitroFile>>>>; + inline Result_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile____ create_Result_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile____(const std::shared_ptr, NitroFile>>>& value) noexcept { + return Result, NitroFile>>>>::withValue(value); } - inline Result_std__shared_ptr_Promise_NitroFile___ create_Result_std__shared_ptr_Promise_NitroFile___(const std::exception_ptr& error) noexcept { - return Result>>::withError(error); + inline Result_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile____ create_Result_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile____(const std::exception_ptr& error) noexcept { + return Result, NitroFile>>>>::withError(error); } } // namespace margelo::nitro::nitrofs::bridge::swift diff --git a/nitrogen/generated/ios/NitroFS-Swift-Cxx-Umbrella.hpp b/nitrogen/generated/ios/NitroFS-Swift-Cxx-Umbrella.hpp index 7764649..8b917b0 100644 --- a/nitrogen/generated/ios/NitroFS-Swift-Cxx-Umbrella.hpp +++ b/nitrogen/generated/ios/NitroFS-Swift-Cxx-Umbrella.hpp @@ -12,6 +12,8 @@ namespace margelo::nitro::nitrofs { class HybridNitroFSSpec; } // Forward declaration of `NitroDownloadOptions` to properly resolve imports. namespace margelo::nitro::nitrofs { struct NitroDownloadOptions; } +// Forward declaration of `NitroDownloadOutput` to properly resolve imports. +namespace margelo::nitro::nitrofs { enum class NitroDownloadOutput; } // Forward declaration of `NitroFileEncoding` to properly resolve imports. namespace margelo::nitro::nitrofs { enum class NitroFileEncoding; } // Forward declaration of `NitroFileStat` to properly resolve imports. @@ -26,11 +28,13 @@ namespace margelo::nitro::nitrofs { struct NitroUploadOptions; } // Include C++ defined types #include "HybridNitroFSSpec.hpp" #include "NitroDownloadOptions.hpp" +#include "NitroDownloadOutput.hpp" #include "NitroFile.hpp" #include "NitroFileEncoding.hpp" #include "NitroFileStat.hpp" #include "NitroUploadMethod.hpp" #include "NitroUploadOptions.hpp" +#include #include #include #include @@ -39,6 +43,7 @@ namespace margelo::nitro::nitrofs { struct NitroUploadOptions; } #include #include #include +#include #include // C++ helpers for Swift diff --git a/nitrogen/generated/ios/c++/HybridNitroFSSpecSwift.hpp b/nitrogen/generated/ios/c++/HybridNitroFSSpecSwift.hpp index 93aea98..958b92c 100644 --- a/nitrogen/generated/ios/c++/HybridNitroFSSpecSwift.hpp +++ b/nitrogen/generated/ios/c++/HybridNitroFSSpecSwift.hpp @@ -22,8 +22,12 @@ namespace margelo::nitro::nitrofs { struct NitroFile; } namespace margelo::nitro::nitrofs { struct NitroUploadOptions; } // Forward declaration of `NitroUploadMethod` to properly resolve imports. namespace margelo::nitro::nitrofs { enum class NitroUploadMethod; } +// Forward declaration of `ArrayBufferHolder` to properly resolve imports. +namespace NitroModules { class ArrayBufferHolder; } // Forward declaration of `NitroDownloadOptions` to properly resolve imports. namespace margelo::nitro::nitrofs { struct NitroDownloadOptions; } +// Forward declaration of `NitroDownloadOutput` to properly resolve imports. +namespace margelo::nitro::nitrofs { enum class NitroDownloadOutput; } #include #include @@ -36,7 +40,11 @@ namespace margelo::nitro::nitrofs { struct NitroDownloadOptions; } #include #include #include +#include +#include +#include #include "NitroDownloadOptions.hpp" +#include "NitroDownloadOutput.hpp" #include "NitroFS-Swift-Cxx-Umbrella.hpp" @@ -231,7 +239,7 @@ namespace margelo::nitro::nitrofs { auto __value = std::move(__result.value()); return __value; } - inline std::shared_ptr> downloadFile(const NitroDownloadOptions& downloadOptions, const std::optional>& onProgress) override { + inline std::shared_ptr, NitroFile>>> downloadFile(const NitroDownloadOptions& downloadOptions, const std::optional>& onProgress) override { auto __result = _swiftPart.downloadFile(std::forward(downloadOptions), onProgress); if (__result.hasError()) [[unlikely]] { std::rethrow_exception(__result.error()); diff --git a/nitrogen/generated/ios/swift/Func_void_NitroFile.swift b/nitrogen/generated/ios/swift/Func_void_NitroFile.swift deleted file mode 100644 index 1873071..0000000 --- a/nitrogen/generated/ios/swift/Func_void_NitroFile.swift +++ /dev/null @@ -1,46 +0,0 @@ -/// -/// Func_void_NitroFile.swift -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -import NitroModules - -/** - * Wraps a Swift `(_ value: NitroFile) -> Void` as a class. - * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. - */ -public final class Func_void_NitroFile { - public typealias bridge = margelo.nitro.nitrofs.bridge.swift - - private let closure: (_ value: NitroFile) -> Void - - public init(_ closure: @escaping (_ value: NitroFile) -> Void) { - self.closure = closure - } - - @inline(__always) - public func call(value: NitroFile) -> Void { - self.closure(value) - } - - /** - * Casts this instance to a retained unsafe raw pointer. - * This acquires one additional strong reference on the object! - */ - @inline(__always) - public func toUnsafe() -> UnsafeMutableRawPointer { - return Unmanaged.passRetained(self).toOpaque() - } - - /** - * Casts an unsafe pointer to a `Func_void_NitroFile`. - * The pointer has to be a retained opaque `Unmanaged`. - * This removes one strong reference from the object! - */ - @inline(__always) - public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_NitroFile { - return Unmanaged.fromOpaque(pointer).takeRetainedValue() - } -} diff --git a/nitrogen/generated/ios/swift/Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_.swift b/nitrogen/generated/ios/swift/Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_.swift new file mode 100644 index 0000000..82baa60 --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_.swift @@ -0,0 +1,58 @@ +/// +/// Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Wraps a Swift `(_ value: NitroDownloadResult) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_ { + public typealias bridge = margelo.nitro.nitrofs.bridge.swift + + private let closure: (_ value: NitroDownloadResult) -> Void + + public init(_ closure: @escaping (_ value: NitroDownloadResult) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(value: bridge.std__variant_std__shared_ptr_ArrayBuffer___NitroFile_) -> Void { + self.closure({ () -> NitroDownloadResult in + let __variant = value + switch __variant.index() { + case 0: + let __actual = __variant.get_0() + return .first(ArrayBuffer(__actual)) + case 1: + let __actual = __variant.get_1() + return .second(__actual) + default: + fatalError("Variant can never have index \(__variant.index())!") + } + }()) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_ { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/HybridNitroFSSpec.swift b/nitrogen/generated/ios/swift/HybridNitroFSSpec.swift index 37867a5..e0e432a 100644 --- a/nitrogen/generated/ios/swift/HybridNitroFSSpec.swift +++ b/nitrogen/generated/ios/swift/HybridNitroFSSpec.swift @@ -34,7 +34,7 @@ public protocol HybridNitroFSSpec_protocol: HybridObject { func basename(path: String) throws -> String func extname(path: String) throws -> String func uploadFile(uploadOptions: NitroUploadOptions, onProgress: ((_ uploadedBytes: Double, _ totalBytes: Double) -> Void)?) throws -> Promise - func downloadFile(downloadOptions: NitroDownloadOptions, onProgress: ((_ downloadedBytes: Double, _ totalBytes: Double) -> Void)?) throws -> Promise + func downloadFile(downloadOptions: NitroDownloadOptions, onProgress: ((_ downloadedBytes: Double, _ totalBytes: Double) -> Void)?) throws -> Promise } public extension HybridNitroFSSpec_protocol { diff --git a/nitrogen/generated/ios/swift/HybridNitroFSSpec_cxx.swift b/nitrogen/generated/ios/swift/HybridNitroFSSpec_cxx.swift index 63d854c..59d0f7f 100644 --- a/nitrogen/generated/ios/swift/HybridNitroFSSpec_cxx.swift +++ b/nitrogen/generated/ios/swift/HybridNitroFSSpec_cxx.swift @@ -442,7 +442,7 @@ open class HybridNitroFSSpec_cxx { } @inline(__always) - public final func downloadFile(downloadOptions: NitroDownloadOptions, onProgress: bridge.std__optional_std__function_void_double____downloadedBytes_____double____totalBytes______) -> bridge.Result_std__shared_ptr_Promise_NitroFile___ { + public final func downloadFile(downloadOptions: NitroDownloadOptions, onProgress: bridge.std__optional_std__function_void_double____downloadedBytes_____double____totalBytes______) -> bridge.Result_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile____ { do { let __result = try self.__implementation.downloadFile(downloadOptions: downloadOptions, onProgress: { () -> ((_ downloadedBytes: Double, _ totalBytes: Double) -> Void)? in if bridge.has_value_std__optional_std__function_void_double____downloadedBytes_____double____totalBytes______(onProgress) { @@ -457,18 +457,25 @@ open class HybridNitroFSSpec_cxx { return nil } }()) - let __resultCpp = { () -> bridge.std__shared_ptr_Promise_NitroFile__ in - let __promise = bridge.create_std__shared_ptr_Promise_NitroFile__() - let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_NitroFile__(__promise) + let __resultCpp = { () -> bridge.std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile___ in + let __promise = bridge.create_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile___() + let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile___(__promise) __result - .then({ __result in __promiseHolder.resolve(__result) }) + .then({ __result in __promiseHolder.resolve({ () -> bridge.std__variant_std__shared_ptr_ArrayBuffer___NitroFile_ in + switch __result { + case .first(let __value): + return bridge.create_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_(__value.getArrayBuffer()) + case .second(let __value): + return bridge.create_std__variant_std__shared_ptr_ArrayBuffer___NitroFile_(__value) + } + }().variant) }) .catch({ __error in __promiseHolder.reject(__error.toCpp()) }) return __promise }() - return bridge.create_Result_std__shared_ptr_Promise_NitroFile___(__resultCpp) + return bridge.create_Result_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile____(__resultCpp) } catch (let __error) { let __exceptionPtr = __error.toCpp() - return bridge.create_Result_std__shared_ptr_Promise_NitroFile___(__exceptionPtr) + return bridge.create_Result_std__shared_ptr_Promise_std__variant_std__shared_ptr_ArrayBuffer___NitroFile____(__exceptionPtr) } } } diff --git a/nitrogen/generated/ios/swift/NitroDownloadOptions.swift b/nitrogen/generated/ios/swift/NitroDownloadOptions.swift index bd5395f..9acaada 100644 --- a/nitrogen/generated/ios/swift/NitroDownloadOptions.swift +++ b/nitrogen/generated/ios/swift/NitroDownloadOptions.swift @@ -18,7 +18,7 @@ public extension NitroDownloadOptions { /** * Create a new instance of `NitroDownloadOptions`. */ - init(url: String, destinationPath: String, headers: Dictionary?) { + init(url: String, destinationPath: String, headers: Dictionary?, output: NitroDownloadOutput?) { self.init(std.string(url), std.string(destinationPath), { () -> bridge.std__optional_std__unordered_map_std__string__std__string__ in if let __unwrappedValue = headers { return bridge.create_std__optional_std__unordered_map_std__string__std__string__({ () -> bridge.std__unordered_map_std__string__std__string_ in @@ -31,6 +31,12 @@ public extension NitroDownloadOptions { } else { return .init() } + }(), { () -> bridge.std__optional_NitroDownloadOutput_ in + if let __unwrappedValue = output { + return bridge.create_std__optional_NitroDownloadOutput_(__unwrappedValue) + } else { + return .init() + } }()) } @@ -38,12 +44,12 @@ public extension NitroDownloadOptions { var url: String { return String(self.__url) } - + @inline(__always) var destinationPath: String { return String(self.__destinationPath) } - + @inline(__always) var headers: Dictionary? { return { () -> Dictionary? in @@ -63,4 +69,9 @@ public extension NitroDownloadOptions { } }() } + + @inline(__always) + var output: NitroDownloadOutput? { + return self.__output.value + } } diff --git a/nitrogen/generated/ios/swift/NitroDownloadOutput.swift b/nitrogen/generated/ios/swift/NitroDownloadOutput.swift new file mode 100644 index 0000000..abfafae --- /dev/null +++ b/nitrogen/generated/ios/swift/NitroDownloadOutput.swift @@ -0,0 +1,40 @@ +/// +/// NitroDownloadOutput.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +/** + * Represents the JS union `NitroDownloadOutput`, backed by a C++ enum. + */ +public typealias NitroDownloadOutput = margelo.nitro.nitrofs.NitroDownloadOutput + +public extension NitroDownloadOutput { + /** + * Get a NitroDownloadOutput for the given String value, or + * return `nil` if the given value was invalid/unknown. + */ + init?(fromString string: String) { + switch string { + case "file": + self = .file + case "arrayBuffer": + self = .arraybuffer + default: + return nil + } + } + + /** + * Get the String value this NitroDownloadOutput represents. + */ + var stringValue: String { + switch self { + case .file: + return "file" + case .arraybuffer: + return "arrayBuffer" + } + } +} diff --git a/nitrogen/generated/ios/swift/NitroDownloadResult.swift b/nitrogen/generated/ios/swift/NitroDownloadResult.swift new file mode 100644 index 0000000..e6753a9 --- /dev/null +++ b/nitrogen/generated/ios/swift/NitroDownloadResult.swift @@ -0,0 +1,30 @@ +/// +/// NitroDownloadResult.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * An Swift enum with associated values representing a Variant/Union type. + * JS type: `array-buffer | struct` + */ +@frozen +public indirect enum NitroDownloadResult { + case first(ArrayBuffer) + case second(NitroFile) +} + +public extension NitroDownloadResult { + func asType(_ type: T.Type = T.self) -> T? { + switch self { + case .first(let value): return value as? T + case .second(let value): return value as? T + } + } + func isType(_ type: T.Type = T.self) -> Bool { + return self.asType(type) != nil + } +} diff --git a/nitrogen/generated/shared/c++/HybridNitroFSSpec.hpp b/nitrogen/generated/shared/c++/HybridNitroFSSpec.hpp index 4373df1..eee27c7 100644 --- a/nitrogen/generated/shared/c++/HybridNitroFSSpec.hpp +++ b/nitrogen/generated/shared/c++/HybridNitroFSSpec.hpp @@ -33,6 +33,8 @@ namespace margelo::nitro::nitrofs { struct NitroDownloadOptions; } #include "NitroUploadOptions.hpp" #include #include +#include +#include #include "NitroDownloadOptions.hpp" namespace margelo::nitro::nitrofs { @@ -87,7 +89,7 @@ namespace margelo::nitro::nitrofs { virtual std::string basename(const std::string& path) = 0; virtual std::string extname(const std::string& path) = 0; virtual std::shared_ptr> uploadFile(const NitroUploadOptions& uploadOptions, const std::optional>& onProgress) = 0; - virtual std::shared_ptr> downloadFile(const NitroDownloadOptions& downloadOptions, const std::optional>& onProgress) = 0; + virtual std::shared_ptr, NitroFile>>> downloadFile(const NitroDownloadOptions& downloadOptions, const std::optional>& onProgress) = 0; protected: // Hybrid Setup diff --git a/nitrogen/generated/shared/c++/NitroDownloadOptions.hpp b/nitrogen/generated/shared/c++/NitroDownloadOptions.hpp index 24ce77b..116f6f4 100644 --- a/nitrogen/generated/shared/c++/NitroDownloadOptions.hpp +++ b/nitrogen/generated/shared/c++/NitroDownloadOptions.hpp @@ -28,11 +28,13 @@ #error NitroModules cannot be found! Are you sure you installed NitroModules properly? #endif - +// Forward declaration of `NitroDownloadOutput` to properly resolve imports. +namespace margelo::nitro::nitrofs { enum class NitroDownloadOutput; } #include #include #include +#include "NitroDownloadOutput.hpp" namespace margelo::nitro::nitrofs { @@ -44,10 +46,11 @@ namespace margelo::nitro::nitrofs { std::string url SWIFT_PRIVATE; std::string destinationPath SWIFT_PRIVATE; std::optional> headers SWIFT_PRIVATE; + std::optional output SWIFT_PRIVATE; public: NitroDownloadOptions() = default; - explicit NitroDownloadOptions(std::string url, std::string destinationPath, std::optional> headers): url(url), destinationPath(destinationPath), headers(headers) {} + explicit NitroDownloadOptions(std::string url, std::string destinationPath, std::optional> headers, std::optional output): url(url), destinationPath(destinationPath), headers(headers), output(output) {} public: friend bool operator==(const NitroDownloadOptions& lhs, const NitroDownloadOptions& rhs) = default; @@ -65,7 +68,8 @@ namespace margelo::nitro { return margelo::nitro::nitrofs::NitroDownloadOptions( JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "url"))), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "destinationPath"))), - JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "headers"))) + JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "headers"))), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "output"))) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::nitrofs::NitroDownloadOptions& arg) { @@ -73,6 +77,7 @@ namespace margelo::nitro { obj.setProperty(runtime, PropNameIDCache::get(runtime, "url"), JSIConverter::toJSI(runtime, arg.url)); obj.setProperty(runtime, PropNameIDCache::get(runtime, "destinationPath"), JSIConverter::toJSI(runtime, arg.destinationPath)); obj.setProperty(runtime, PropNameIDCache::get(runtime, "headers"), JSIConverter>>::toJSI(runtime, arg.headers)); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "output"), JSIConverter>::toJSI(runtime, arg.output)); return obj; } static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { @@ -86,6 +91,7 @@ namespace margelo::nitro { if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "url")))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "destinationPath")))) return false; if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "headers")))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "output")))) return false; return true; } }; diff --git a/nitrogen/generated/shared/c++/NitroDownloadOutput.hpp b/nitrogen/generated/shared/c++/NitroDownloadOutput.hpp new file mode 100644 index 0000000..9dbbd02 --- /dev/null +++ b/nitrogen/generated/shared/c++/NitroDownloadOutput.hpp @@ -0,0 +1,76 @@ +/// +/// NitroDownloadOutput.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +namespace margelo::nitro::nitrofs { + + /** + * An enum which can be represented as a JavaScript union (NitroDownloadOutput). + */ + enum class NitroDownloadOutput { + FILE SWIFT_NAME(file) = 0, + ARRAYBUFFER SWIFT_NAME(arraybuffer) = 1, + } CLOSED_ENUM; + +} // namespace margelo::nitro::nitrofs + +namespace margelo::nitro { + + // C++ NitroDownloadOutput <> JS NitroDownloadOutput (union) + template <> + struct JSIConverter final { + static inline margelo::nitro::nitrofs::NitroDownloadOutput fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("file"): return margelo::nitro::nitrofs::NitroDownloadOutput::FILE; + case hashString("arrayBuffer"): return margelo::nitro::nitrofs::NitroDownloadOutput::ARRAYBUFFER; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum NitroDownloadOutput - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::nitrofs::NitroDownloadOutput arg) { + switch (arg) { + case margelo::nitro::nitrofs::NitroDownloadOutput::FILE: return JSIConverter::toJSI(runtime, "file"); + case margelo::nitro::nitrofs::NitroDownloadOutput::ARRAYBUFFER: return JSIConverter::toJSI(runtime, "arrayBuffer"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert NitroDownloadOutput to JS - invalid value: " + + std::to_string(static_cast(arg)) + "!"); + } + } + static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isString()) { + return false; + } + std::string unionValue = JSIConverter::fromJSI(runtime, value); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("file"): + case hashString("arrayBuffer"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/src/specs/nitro-fs.nitro.ts b/src/specs/nitro-fs.nitro.ts index 953ce00..2193bcd 100755 --- a/src/specs/nitro-fs.nitro.ts +++ b/src/specs/nitro-fs.nitro.ts @@ -2,6 +2,7 @@ import type { HybridObject } from 'react-native-nitro-modules' import type { NitroDownloadOptions, + NitroDownloadResult, NitroFile, NitroFileEncoding, NitroFileStat, @@ -154,5 +155,5 @@ export interface NitroFS extends HybridObject<{ ios: 'swift', android: 'kotlin' * console.log(file) // { name: 'file.txt', mimeType: 'text/plain', path: 'file.txt' } * ``` */ - downloadFile(downloadOptions: NitroDownloadOptions, onProgress?: (downloadedBytes: number, totalBytes: number) => void): Promise + downloadFile(downloadOptions: NitroDownloadOptions, onProgress?: (downloadedBytes: number, totalBytes: number) => void): Promise } diff --git a/src/type.ts b/src/type.ts index 7bd9e0e..9db3fec 100644 --- a/src/type.ts +++ b/src/type.ts @@ -2,6 +2,8 @@ export type NitroFileEncoding = 'utf8' | 'ascii' | 'base64' export type NitroUploadMethod = 'POST' | 'PUT' | 'PATCH' +export type NitroDownloadOutput = 'file' | 'arrayBuffer' + export interface NitroUploadOptions { /** * The path to the file to upload @@ -39,6 +41,12 @@ export interface NitroDownloadOptions { * The headers to send with the download request */ headers?: Record + /** + * The value returned after downloading the file. + * + * @default 'file' + */ + output?: NitroDownloadOutput } export type NitroFile = { @@ -47,6 +55,8 @@ export type NitroFile = { path: string } +export type NitroDownloadResult = NitroFile | ArrayBuffer + export type NitroFileStat = { size: number ctime: number