Need help making lz4 compress/decompress blueprint

Here’s a first attempt :

//.h
UFUNCTION(BlueprintCallable)
static int32 LZ4_Compress(const FString& Input, FString& Result);

//.cpp
#include "TraceLog/Private/Trace/LZ4/lz4.c.inl"

int32 UMyLib::LZ4_Compress(const FString& Input, FString& Result)
{
    TArray<TCHAR> TCharArray = Input.GetCharArray();
    TArray<uint8> Bytes;
    Bytes.Reserve(TCharArray.Num() * sizeof(TCHAR));
    for (int i = 0; i < Input.Len(); i++)
    {
        uint8 CharBytes[sizeof(TCHAR)];
        FMemory::Memcpy(&CharBytes[0], &TCharArray[i], sizeof(TCHAR));
        for (int CharIdx = 0; CharIdx < sizeof(TCHAR); CharIdx++)
        {
            Bytes.Add(CharBytes[CharIdx]);
        }
    }

    char* src = reinterpret_cast<char*>(Bytes.GetData());
    int32 inputSize = Bytes.Num();
    int bound = LZ4_compressBound(inputSize);
    char* dst = (char*)FMemory::Malloc(bound + 1);
    int32 written = LZ4_compress_default(src, dst, inputSize, bound);
    dst[written] = '\0';
    Result = dst;
    FMemory::Free(dst);
    return written;
}

Note that the compressed buffer can contain zeroes (string terminators) so it is probably a very bad idea to store the result back in a FString.
Unfortunately blueprints do not support things like uint8* or TArray<uint8> so it’s gonna be difficult to send such a binary buffer over the network via standard RPCs.
I can think of two possible approaches :

  1. Wrap results in a custom USTRUCT, store the buffer natively (it won’t be visible to BP, but you’ll still be able to pass the struct around), and write custom serializer for networking.

  2. Convert the result buffer into a TArray<int32>, by merging bytes 4 by 4, so you can actually use it in blueprints.