101arrowz / fzstd

High performance Zstandard decompression in a pure JavaScript, 8kB package
MIT License
211 stars 11 forks source link

Decompression seemingly not working - "invalid zstd data" #16

Closed kittenswolf closed 1 week ago

kittenswolf commented 2 weeks ago

I'm probably missing something, but for me decompression does not work.

I first tried using the python port to compress a short string and then decompress it:

import base64
import zstandard
input_string = "testing 123"
cctx = zstandard.ZstdCompressor(level=1, write_checksum=True, write_content_size=True)
compressed_bytes = cctx.compress(input_string.encode())
base64_encoded = base64.b64encode(compressed_bytes).decode() # --> 'KLUv/SQLWQAAdGVzdGluZyAxMjMte7Nh'
$ node
Welcome to Node.js v20.7.0.
Type ".help" for more information.
> const fzstd = require('fzstd');
undefined
> fzstd.decompress(atob('KLUv/SQLWQAAdGVzdGluZyAxMjMte7Nh'))
Uncaught Error: invalid zstd data
    at rzfh (/~?/node_modules/fzstd/lib/index.js:123:5)
    at Object.decompress (/~?/node_modules/fzstd/lib/index.js:618:18) {
  code: 0
}

My second attempt didn't work either:

$ echo "testing 123" > input_file
$ zstd input_file
input_file           :208.33%   (    12 =>     25 bytes, input_file.zst)
$ base64 input_file.zst
KLUv/SQMYQAAdGVzdGluZyAxMjMKzoyaWg==
$
$ node
Welcome to Node.js v20.7.0.
Type ".help" for more information.
> const fzstd = require('fzstd');
undefined
> fzstd.decompress(atob('KLUv/SQMYQAAdGVzdGluZyAxMjMKzoyaWg=='))
Uncaught Error: invalid zstd data
    at rzfh (/~?/node_modules/fzstd/lib/index.js:123:5)
    at Object.decompress (/~?/node_modules/fzstd/lib/index.js:618:18) {
  code: 0
}
>

What am I missing?

101arrowz commented 2 weeks ago

You need to use Uint8Array only with fzstd; you're passing in a binary string (i.e. a string where each character has a character code mapping to a byte value from 0-255). There's a short conversion process, here's how you can do it:

const binString = atob('KLUv/SQMYQAAdGVzdGluZyAxMjMKzoyaWg==');
const compressed = new Uint8Array(binString.split('').map(char => char.charCodeAt(0)));

const decompressed = fzstd.decompress(compressed);

// if you want to turn it back into a string:
const decompressedString = new TextDecoder().decode(decompressed);
kittenswolf commented 1 week ago

@101arrowz That works! I knew I missed something. Thanks :-)