| 1 | @[deprecated: 'use compress.deflate instead'] |
| 2 | @[deprecated_after: '2026-07-31'] |
| 3 | module compress |
| 4 | |
| 5 | #flag -I @VEXEROOT/thirdparty/zip |
| 6 | #define MINIZ_NO_ZLIB_COMPATIBLE_NAMES |
| 7 | #include "miniz.h" |
| 8 | |
| 9 | @[deprecated: 'use max_i32 (from builtin) instead'] |
| 10 | @[deprecated_after: '2026-07-31'] |
| 11 | pub const max_size = u64(1 << 31) |
| 12 | |
| 13 | fn C.tdefl_compress_mem_to_heap(source_buf voidptr, source_buf_len usize, out_len &usize, flags i32) voidptr |
| 14 | fn C.tinfl_decompress_mem_to_heap(source_buf voidptr, source_buf_len usize, out_len &usize, flags i32) voidptr |
| 15 | |
| 16 | // compresses an array of bytes based on providing flags and returns the compressed bytes in a new array |
| 17 | // NB: this is a low level api, a high level implementation like zlib/gzip should be preferred |
| 18 | @[deprecated: 'use compress.deflate.compress instead'] |
| 19 | @[deprecated_after: '2026-07-31'] |
| 20 | @[manualfree] |
| 21 | pub fn compress(data []u8, flags int) ![]u8 { |
| 22 | if u64(data.len) > max_size { |
| 23 | return error('data too large (${data.len} > ${max_size})') |
| 24 | } |
| 25 | mut out_len := usize(0) |
| 26 | |
| 27 | address := C.tdefl_compress_mem_to_heap(data.data, data.len, &out_len, flags) |
| 28 | if address == 0 { |
| 29 | return error('compression failed') |
| 30 | } |
| 31 | if u64(out_len) > max_size { |
| 32 | return error('compressed data is too large (${out_len} > ${max_size})') |
| 33 | } |
| 34 | unsafe { |
| 35 | ret := address.vbytes(int(out_len)).clone() |
| 36 | C.free(address) |
| 37 | return ret |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | // decompresses an array of bytes based on providing flags and returns the decompressed bytes in a new array |
| 42 | // NB: this is a low level api, a high level implementation like zlib/gzip should be preferred |
| 43 | @[deprecated: 'use compress.deflate.decompress instead'] |
| 44 | @[deprecated_after: '2026-07-31'] |
| 45 | @[manualfree] |
| 46 | pub fn decompress(data []u8, flags int) ![]u8 { |
| 47 | mut out_len := usize(0) |
| 48 | |
| 49 | address := C.tinfl_decompress_mem_to_heap(data.data, data.len, &out_len, flags) |
| 50 | if address == 0 { |
| 51 | return error('decompression failed') |
| 52 | } |
| 53 | if u64(out_len) > max_size { |
| 54 | return error('decompressed data is too large (${out_len} > ${max_size})') |
| 55 | } |
| 56 | |
| 57 | unsafe { |
| 58 | ret := address.vbytes(int(out_len)).clone() |
| 59 | C.free(address) |
| 60 | return ret |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | // ChunkCallback is used to receive decompressed chunks of maximum 32768 bytes. |
| 65 | // After processing the chunk this function should return the chunk's length to indicate |
| 66 | // the decompressor to send more chunks, otherwise the decompression stops. |
| 67 | // The userdata parameter comes from the call to decompress_with_callback/4, and can be used |
| 68 | // to pass arbitrary data, without having to create a closure. |
| 69 | |
| 70 | @[deprecated: 'use compress.deflate.ChunkCallback instead'] |
| 71 | @[deprecated_after: '2026-07-31'] |
| 72 | pub type ChunkCallback = fn (chunk []u8, userdata voidptr) int |
| 73 | |
| 74 | // decompress_with_callback decompresses an array of bytes, based on the provided flags, and a V fn callback to receive decompressed chunks, of at most 32 kilobytes each. |
| 75 | // It returns the total decompressed length, or a decompression error. |
| 76 | // NB: this is a low level api, a high level implementation like zlib/gzip should be preferred. |
| 77 | @[deprecated: 'use compress.deflate.decompress_with_callback instead'] |
| 78 | @[deprecated_after: '2026-07-31'] |
| 79 | pub fn decompress_with_callback(data []u8, cb ChunkCallback, userdata voidptr, flags int) !u64 { |
| 80 | cbdata := DecompressionCallBackData{ |
| 81 | data: data.data |
| 82 | size: usize(data.len) |
| 83 | cb: cb |
| 84 | userdata: userdata |
| 85 | } |
| 86 | status := C.tinfl_decompress_mem_to_callback(cbdata.data, &cbdata.size, |
| 87 | c_cb_for_decompress_mem, &cbdata, flags) |
| 88 | if status == 0 { |
| 89 | return error('decompression error') |
| 90 | } |
| 91 | return cbdata.decompressed_size |
| 92 | } |
| 93 | |
| 94 | struct DecompressionCallBackData { |
| 95 | mut: |
| 96 | data voidptr |
| 97 | size usize |
| 98 | decompressed_size u64 |
| 99 | userdata voidptr |
| 100 | cb ChunkCallback = unsafe { nil } |
| 101 | } |
| 102 | |
| 103 | fn c_cb_for_decompress_mem(buf &char, len int, pdcbd voidptr) int { |
| 104 | mut cbdata := unsafe { &DecompressionCallBackData(pdcbd) } |
| 105 | if cbdata.cb(unsafe { voidptr(buf).vbytes(len) }, cbdata.userdata) == len { |
| 106 | cbdata.decompressed_size += u64(len) |
| 107 | return 1 // continue decompressing |
| 108 | } |
| 109 | return 0 // stop decompressing |
| 110 | } |
| 111 | |
| 112 | type DecompressCallback = fn (const_buffer voidptr, len int, userdata voidptr) int |
| 113 | |
| 114 | fn C.tinfl_decompress_mem_to_callback(const_input_buffer voidptr, psize &usize, put_buf_cb DecompressCallback, userdata voidptr, flags i32) i32 |
| 115 | |