1 module zstd.decompress;
2 
3 import zstd.c.zstd;
4 import zstd.common;
5 
6 void[] uncompress(const(void)[] src)
7 {
8     auto destCap = ZSTD_getDecompressedSize(src.ptr, src.length);
9     if (destCap == 0)
10         throw new ZstdException("Unknown original size. Use stream API");
11 
12     auto destBuf = new ubyte[destCap];
13     auto result = ZSTD_decompress(destBuf.ptr, destCap, src.ptr, src.length);
14     if (ZSTD_isError(result)) {
15         destBuf = null;
16         throw new ZstdException(result);
17     }
18 
19     return destBuf[0..result];
20 }
21 
22 class Decompressor
23 {
24   private:
25     ZSTD_DStream* dstream;
26     ubyte[] buffer;
27 
28   public:
29     @property @trusted static
30     {
31         size_t recommendedInSize()
32         {
33             return ZSTD_DStreamInSize();
34         }
35 
36         size_t recommendedOutSize()
37         {
38             return ZSTD_DStreamOutSize();
39         }
40     }
41 
42     this()
43     {
44         dstream = ZSTD_createDStream();
45         buffer = new ubyte[](recommendedOutSize);
46         size_t result = ZSTD_initDStream(dstream);
47         if (ZSTD_isError(result))
48             throw new ZstdException(result);
49     }
50 
51     ~this()
52     {
53         closeStream();
54     }
55 
56     ubyte[] decompress(const(void)[] src)
57     {
58         ubyte[] result;
59         ZSTD_inBuffer input = {src.ptr, src.length, 0};
60         ZSTD_outBuffer output = {buffer.ptr, buffer.length, 0};
61 
62         while (input.pos < input.size) {
63             output.pos = 0;
64             size_t code = ZSTD_decompressStream(dstream, &output, &input);
65             if (ZSTD_isError(code))
66                 throw new ZstdException(code);
67             result ~= buffer[0..output.pos];
68         }
69 
70         return result;
71     }
72 
73     ubyte[] flush()
74     {
75         return null;
76     }
77 
78     ubyte[] finish()
79     {
80         closeStream();
81 
82         return null;
83     }
84 
85   private:
86     void closeStream()
87     {
88         if (dstream) {
89             ZSTD_freeDStream(dstream);
90             dstream = null;
91         }
92     }
93 }
94