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