diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
index 33ebb8171e8..b6073c5cfc9 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
@@ -682,5 +682,53 @@ namespace Godot
{
return Marshaling.ConvertManagedTypeToVariantType(type, out bool _);
}
+
+ ///
+ /// Returns a new byte array with the data compressed.
+ ///
+ /// The byte array to compress.
+ /// The compression mode, one of
+ /// The compressed byte array.
+ public static byte[] Compress(this byte[] instance, FileAccess.CompressionMode compressionMode = 0)
+ {
+ using godot_packed_byte_array src = Marshaling.ConvertSystemArrayToNativePackedByteArray(instance);
+ NativeFuncs.godotsharp_packed_byte_array_compress(src, (int)compressionMode, out var ret);
+ using (ret)
+ return Marshaling.ConvertNativePackedByteArrayToSystemArray(ret);
+ }
+
+ ///
+ /// Returns a new byte array with the data decompressed.
+ /// Note: Decompression is not guaranteed to work with data not compressed by Godot, for example if data compressed with the deflate compression mode lacks a checksum or header.
+ ///
+ /// The byte array to decompress.
+ /// The size of the uncompressed data.
+ /// The compression mode, one of
+ /// The decompressed byte array.
+ public static byte[] Decompress(this byte[] instance, long bufferSize, FileAccess.CompressionMode compressionMode = 0)
+ {
+ using godot_packed_byte_array src = Marshaling.ConvertSystemArrayToNativePackedByteArray(instance);
+ NativeFuncs.godotsharp_packed_byte_array_decompress(src, bufferSize, (int)compressionMode, out var ret);
+ using (ret)
+ return Marshaling.ConvertNativePackedByteArrayToSystemArray(ret);
+ }
+
+ ///
+ /// Returns a new byte array with the data decompressed. This method only accepts brotli, gzip, and deflate compression modes.
+ /// This method is potentially slower than , as it may have to re-allocate its output buffer multiple times while decompressing, whereas knows it's output buffer size from the beginning.
+ /// GZIP has a maximal compression ratio of 1032:1, meaning it's very possible for a small compressed payload to decompress to a potentially very large output. To guard against this, you may provide a maximum size this function is allowed to allocate in bytes via [param max_output_size]. Passing -1 will allow for unbounded output. If any positive value is passed, and the decompression exceeds that amount in bytes, then an error will be returned.
+ /// Note: Decompression is not guaranteed to work with data not compressed by Godot, for example if data compressed with the deflate compression mode lacks a checksum or header.
+ ///
+ /// The byte array to decompress.
+ /// The maximum size this function is allowed to allocate in bytes.
+ /// The compression mode, one of
+ /// The decompressed byte array.
+ public static byte[] DecompressDynamic(this byte[] instance, long maxOutputSize, FileAccess.CompressionMode compressionMode = 0)
+ {
+ using godot_packed_byte_array src = Marshaling.ConvertSystemArrayToNativePackedByteArray(instance);
+ NativeFuncs.godotsharp_packed_byte_array_decompress_dynamic(src, maxOutputSize, (int)compressionMode, out var ret);
+ using (ret)
+ return Marshaling.ConvertNativePackedByteArrayToSystemArray(ret);
+ }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
index d42d101a11a..25b343c8ef9 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
@@ -433,6 +433,12 @@ namespace Godot.NativeInterop
public static partial void godotsharp_array_to_string(ref godot_array p_self, out godot_string r_str);
+ public static partial void godotsharp_packed_byte_array_compress(scoped in godot_packed_byte_array p_src, int p_mode, out godot_packed_byte_array r_dst);
+
+ public static partial void godotsharp_packed_byte_array_decompress(scoped in godot_packed_byte_array p_src, long p_buffer_size, int p_mode, out godot_packed_byte_array r_dst);
+
+ public static partial void godotsharp_packed_byte_array_decompress_dynamic(scoped in godot_packed_byte_array p_src, long p_buffer_size, int p_mode, out godot_packed_byte_array r_dst);
+
// Dictionary
public static partial godot_bool godotsharp_dictionary_try_get_value(scoped ref godot_dictionary p_self,
diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp
index abe174306eb..d4d762f08ce 100644
--- a/modules/mono/glue/runtime_interop.cpp
+++ b/modules/mono/glue/runtime_interop.cpp
@@ -1168,6 +1168,47 @@ void godotsharp_array_to_string(const Array *p_self, String *r_str) {
*r_str = Variant(*p_self).operator String();
}
+void godotsharp_packed_byte_array_compress(const PackedByteArray *p_src, int p_mode, PackedByteArray *r_dst) {
+ if (p_src->size() > 0) {
+ Compression::Mode mode = (Compression::Mode)(p_mode);
+ r_dst->resize(Compression::get_max_compressed_buffer_size(p_src->size(), mode));
+ int result = Compression::compress(r_dst->ptrw(), p_src->ptr(), p_src->size(), mode);
+
+ result = result >= 0 ? result : 0;
+ r_dst->resize(result);
+ }
+}
+
+void godotsharp_packed_byte_array_decompress(const PackedByteArray *p_src, int64_t p_buffer_size, int p_mode, PackedByteArray *r_dst) {
+ int64_t buffer_size = p_buffer_size;
+ Compression::Mode mode = (Compression::Mode)(p_mode);
+
+ if (buffer_size <= 0) {
+ ERR_FAIL_MSG("Decompression buffer size must be greater than zero.");
+ }
+ if (p_src->size() == 0) {
+ ERR_FAIL_MSG("Compressed buffer size must be greater than zero.");
+ }
+
+ r_dst->resize(buffer_size);
+ int result = Compression::decompress(r_dst->ptrw(), buffer_size, p_src->ptr(), p_src->size(), mode);
+
+ result = result >= 0 ? result : 0;
+ r_dst->resize(result);
+}
+
+void godotsharp_packed_byte_array_decompress_dynamic(const PackedByteArray *p_src, int64_t p_max_output_size, int p_mode, PackedByteArray *r_dst) {
+ int64_t max_output_size = p_max_output_size;
+ Compression::Mode mode = (Compression::Mode)(p_mode);
+
+ int result = Compression::decompress_dynamic(r_dst, max_output_size, p_src->ptr(), p_src->size(), mode);
+
+ if (result != OK) {
+ r_dst->clear();
+ ERR_FAIL_MSG("Decompression failed.");
+ }
+}
+
// Dictionary
bool godotsharp_dictionary_try_get_value(const Dictionary *p_self, const Variant *p_key, Variant *r_value) {
@@ -1683,6 +1724,9 @@ static const void *unmanaged_callbacks[]{
(void *)godotsharp_array_slice,
(void *)godotsharp_array_sort,
(void *)godotsharp_array_to_string,
+ (void *)godotsharp_packed_byte_array_compress,
+ (void *)godotsharp_packed_byte_array_decompress,
+ (void *)godotsharp_packed_byte_array_decompress_dynamic,
(void *)godotsharp_dictionary_try_get_value,
(void *)godotsharp_dictionary_set_value,
(void *)godotsharp_dictionary_keys,