diff --git a/native/cpp/CommonCpp/NativeModules/CommUtilsModule.h b/native/cpp/CommonCpp/NativeModules/CommUtilsModule.h --- a/native/cpp/CommonCpp/NativeModules/CommUtilsModule.h +++ b/native/cpp/CommonCpp/NativeModules/CommUtilsModule.h @@ -32,6 +32,10 @@ virtual jsi::Object base64DecodeBuffer(jsi::Runtime &rt, jsi::String base64) override; virtual jsi::String sha256(jsi::Runtime &rt, jsi::Object data) override; + virtual jsi::String + decodeUTF8ArrayBufferToString(jsi::Runtime &rt, jsi::Object data) override; + virtual jsi::Object + encodeStringToUTF8ArrayBuffer(jsi::Runtime &rt, jsi::String str) override; public: CommUtilsModule(std::shared_ptr jsInvoker); diff --git a/native/cpp/CommonCpp/NativeModules/CommUtilsModule.cpp b/native/cpp/CommonCpp/NativeModules/CommUtilsModule.cpp --- a/native/cpp/CommonCpp/NativeModules/CommUtilsModule.cpp +++ b/native/cpp/CommonCpp/NativeModules/CommUtilsModule.cpp @@ -150,4 +150,42 @@ return jsi::String::createFromUtf8(rt, sha256String); } +jsi::String CommUtilsModule::decodeUTF8ArrayBufferToString( + jsi::Runtime &rt, + jsi::Object data) { + auto arrayBuffer = data.getArrayBuffer(rt); + auto dataPtr = arrayBuffer.data(rt); + auto size = arrayBuffer.size(rt); + + auto bytes = std::vector{dataPtr, dataPtr + size}; + auto str = std::string(bytes.begin(), bytes.end()); + jsi::String jsiStr = jsi::String::createFromUtf8(rt, str); + + // createFromUtf8() results are undefined if + // str contains invalid code points. + auto strAfterConversion = jsiStr.utf8(rt); + if (str != strAfterConversion) { + throw jsi::JSError(rt, "Invalid UTF-8 ArrayBuffer"); + } + + return jsiStr; +} + +jsi::Object CommUtilsModule::encodeStringToUTF8ArrayBuffer( + jsi::Runtime &rt, + jsi::String inputStr) { + auto str = inputStr.utf8(rt); + auto bytes = std::vector(str.begin(), str.end()); + auto size = bytes.size(); + + auto arrayBuffer = rt.global() + .getPropertyAsFunction(rt, "ArrayBuffer") + .callAsConstructor(rt, {static_cast(size)}) + .asObject(rt) + .getArrayBuffer(rt); + + memcpy(arrayBuffer.data(rt), bytes.data(), size); + return std::move(arrayBuffer); +} + } // namespace comm diff --git a/native/cpp/CommonCpp/_generated/utilsJSI-generated.cpp b/native/cpp/CommonCpp/_generated/utilsJSI-generated.cpp --- a/native/cpp/CommonCpp/_generated/utilsJSI-generated.cpp +++ b/native/cpp/CommonCpp/_generated/utilsJSI-generated.cpp @@ -27,6 +27,12 @@ static jsi::Value __hostFunction_CommUtilsModuleSchemaCxxSpecJSI_sha256(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->sha256(rt, args[0].asObject(rt)); } +static jsi::Value __hostFunction_CommUtilsModuleSchemaCxxSpecJSI_decodeUTF8ArrayBufferToString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->decodeUTF8ArrayBufferToString(rt, args[0].asObject(rt)); +} +static jsi::Value __hostFunction_CommUtilsModuleSchemaCxxSpecJSI_encodeStringToUTF8ArrayBuffer(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->encodeStringToUTF8ArrayBuffer(rt, args[0].asString(rt)); +} CommUtilsModuleSchemaCxxSpecJSI::CommUtilsModuleSchemaCxxSpecJSI(std::shared_ptr jsInvoker) : TurboModule("CommUtilsTurboModule", jsInvoker) { @@ -35,6 +41,8 @@ methodMap_["base64EncodeBuffer"] = MethodMetadata {1, __hostFunction_CommUtilsModuleSchemaCxxSpecJSI_base64EncodeBuffer}; methodMap_["base64DecodeBuffer"] = MethodMetadata {1, __hostFunction_CommUtilsModuleSchemaCxxSpecJSI_base64DecodeBuffer}; methodMap_["sha256"] = MethodMetadata {1, __hostFunction_CommUtilsModuleSchemaCxxSpecJSI_sha256}; + methodMap_["decodeUTF8ArrayBufferToString"] = MethodMetadata {1, __hostFunction_CommUtilsModuleSchemaCxxSpecJSI_decodeUTF8ArrayBufferToString}; + methodMap_["encodeStringToUTF8ArrayBuffer"] = MethodMetadata {1, __hostFunction_CommUtilsModuleSchemaCxxSpecJSI_encodeStringToUTF8ArrayBuffer}; } diff --git a/native/cpp/CommonCpp/_generated/utilsJSI.h b/native/cpp/CommonCpp/_generated/utilsJSI.h --- a/native/cpp/CommonCpp/_generated/utilsJSI.h +++ b/native/cpp/CommonCpp/_generated/utilsJSI.h @@ -25,6 +25,8 @@ virtual jsi::String base64EncodeBuffer(jsi::Runtime &rt, jsi::Object data) = 0; virtual jsi::Object base64DecodeBuffer(jsi::Runtime &rt, jsi::String base64) = 0; virtual jsi::String sha256(jsi::Runtime &rt, jsi::Object data) = 0; + virtual jsi::String decodeUTF8ArrayBufferToString(jsi::Runtime &rt, jsi::Object data) = 0; + virtual jsi::Object encodeStringToUTF8ArrayBuffer(jsi::Runtime &rt, jsi::String str) = 0; }; @@ -86,6 +88,22 @@ return bridging::callFromJs( rt, &T::sha256, jsInvoker_, instance_, std::move(data)); } + jsi::String decodeUTF8ArrayBufferToString(jsi::Runtime &rt, jsi::Object data) override { + static_assert( + bridging::getParameterCount(&T::decodeUTF8ArrayBufferToString) == 2, + "Expected decodeUTF8ArrayBufferToString(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::decodeUTF8ArrayBufferToString, jsInvoker_, instance_, std::move(data)); + } + jsi::Object encodeStringToUTF8ArrayBuffer(jsi::Runtime &rt, jsi::String str) override { + static_assert( + bridging::getParameterCount(&T::encodeStringToUTF8ArrayBuffer) == 2, + "Expected encodeStringToUTF8ArrayBuffer(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::encodeStringToUTF8ArrayBuffer, jsInvoker_, instance_, std::move(str)); + } private: T *instance_; diff --git a/native/schema/CommUtilsModuleSchema.js b/native/schema/CommUtilsModuleSchema.js --- a/native/schema/CommUtilsModuleSchema.js +++ b/native/schema/CommUtilsModuleSchema.js @@ -15,6 +15,9 @@ +base64DecodeBuffer: (base64: string) => JSIArrayBuffer; // crypto utils +sha256: (data: JSIArrayBuffer) => string; + // encoding utils + +decodeUTF8ArrayBufferToString: (data: JSIArrayBuffer) => string; + +encodeStringToUTF8ArrayBuffer: (str: string) => JSIArrayBuffer; } // for public interface, we use the correct types @@ -24,6 +27,8 @@ +base64EncodeBuffer: (data: ArrayBuffer) => string; +base64DecodeBuffer: (base64: string) => ArrayBuffer; +sha256: (data: ArrayBuffer) => string; + +decodeUTF8ArrayBufferToString: (data: ArrayBuffer) => string; + +encodeStringToUTF8ArrayBuffer: (str: string) => ArrayBuffer; } export default (TurboModuleRegistry.getEnforcing(