v / vlib / compress / compress.c.v
114 lines · 99 sloc · 4.15 KB · 02d9ab594d19c672bbfc9f290201f39697949f7a
Raw
1@[deprecated: 'use compress.deflate instead']
2@[deprecated_after: '2026-07-31']
3module 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']
11pub const max_size = u64(1 << 31)
12
13fn C.tdefl_compress_mem_to_heap(source_buf voidptr, source_buf_len usize, out_len &usize, flags i32) voidptr
14fn 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]
21pub 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]
46pub 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']
72pub 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']
79pub 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
94struct DecompressionCallBackData {
95mut:
96 data voidptr
97 size usize
98 decompressed_size u64
99 userdata voidptr
100 cb ChunkCallback = unsafe { nil }
101}
102
103fn 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
112type DecompressCallback = fn (const_buffer voidptr, len int, userdata voidptr) int
113
114fn C.tinfl_decompress_mem_to_callback(const_input_buffer voidptr, psize &usize, put_buf_cb DecompressCallback, userdata voidptr, flags i32) i32
115