node-liblzma 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +431 -727
- package/index.d.ts +34 -0
- package/lib/cli/nxz.d.ts +7 -0
- package/lib/cli/nxz.d.ts.map +1 -0
- package/lib/cli/nxz.js +578 -0
- package/lib/cli/nxz.js.map +1 -0
- package/lib/lzma.browser.d.ts +24 -0
- package/lib/lzma.browser.d.ts.map +1 -0
- package/lib/lzma.browser.js +30 -0
- package/lib/lzma.browser.js.map +1 -0
- package/lib/lzma.d.ts +83 -0
- package/lib/lzma.d.ts.map +1 -1
- package/lib/lzma.inline.d.ts +30 -0
- package/lib/lzma.inline.d.ts.map +1 -0
- package/lib/lzma.inline.js +68 -0
- package/lib/lzma.inline.js.map +1 -0
- package/lib/lzma.js +78 -0
- package/lib/lzma.js.map +1 -1
- package/lib/wasm/bindings.d.ts +109 -0
- package/lib/wasm/bindings.d.ts.map +1 -0
- package/lib/wasm/bindings.js +307 -0
- package/lib/wasm/bindings.js.map +1 -0
- package/lib/wasm/compress.d.ts +32 -0
- package/lib/wasm/compress.d.ts.map +1 -0
- package/lib/wasm/compress.js +47 -0
- package/lib/wasm/compress.js.map +1 -0
- package/lib/wasm/decompress.d.ts +32 -0
- package/lib/wasm/decompress.d.ts.map +1 -0
- package/lib/wasm/decompress.js +45 -0
- package/lib/wasm/decompress.js.map +1 -0
- package/lib/wasm/index.d.ts +14 -0
- package/lib/wasm/index.d.ts.map +1 -0
- package/lib/wasm/index.js +18 -0
- package/lib/wasm/index.js.map +1 -0
- package/lib/wasm/liblzma.inline.d.ts +10 -0
- package/lib/wasm/liblzma.inline.d.ts.map +1 -0
- package/lib/wasm/liblzma.inline.js +10 -0
- package/lib/wasm/liblzma.inline.js.map +1 -0
- package/lib/wasm/memory.d.ts +57 -0
- package/lib/wasm/memory.d.ts.map +1 -0
- package/lib/wasm/memory.js +108 -0
- package/lib/wasm/memory.js.map +1 -0
- package/lib/wasm/stream.d.ts +35 -0
- package/lib/wasm/stream.d.ts.map +1 -0
- package/lib/wasm/stream.js +164 -0
- package/lib/wasm/stream.js.map +1 -0
- package/lib/wasm/types.d.ts +77 -0
- package/lib/wasm/types.d.ts.map +1 -0
- package/lib/wasm/types.js +55 -0
- package/lib/wasm/types.js.map +1 -0
- package/lib/wasm/utils.d.ts +62 -0
- package/lib/wasm/utils.d.ts.map +1 -0
- package/lib/wasm/utils.js +162 -0
- package/lib/wasm/utils.js.map +1 -0
- package/package.json +27 -3
- package/src/bindings/module.cpp +196 -0
package/src/bindings/module.cpp
CHANGED
|
@@ -17,6 +17,193 @@
|
|
|
17
17
|
**/
|
|
18
18
|
|
|
19
19
|
#include "node-liblzma.hpp"
|
|
20
|
+
#include <cstring>
|
|
21
|
+
|
|
22
|
+
// XZ magic bytes: 0xFD + "7zXZ" + 0x00
|
|
23
|
+
static const uint8_t XZ_MAGIC[6] = {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Check if a buffer starts with the XZ magic bytes.
|
|
27
|
+
* @param info[0] Buffer to check
|
|
28
|
+
* @returns true if the buffer is an XZ stream, false otherwise
|
|
29
|
+
*/
|
|
30
|
+
Napi::Value IsXZ(const Napi::CallbackInfo &info)
|
|
31
|
+
{
|
|
32
|
+
Napi::Env env = info.Env();
|
|
33
|
+
|
|
34
|
+
if (info.Length() < 1 || !info[0].IsBuffer())
|
|
35
|
+
{
|
|
36
|
+
Napi::TypeError::New(env, "Expected a Buffer argument").ThrowAsJavaScriptException();
|
|
37
|
+
return env.Null();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Napi::Buffer<uint8_t> buf = info[0].As<Napi::Buffer<uint8_t>>();
|
|
41
|
+
|
|
42
|
+
// Need at least 6 bytes for XZ magic
|
|
43
|
+
if (buf.Length() < 6)
|
|
44
|
+
{
|
|
45
|
+
return Napi::Boolean::New(env, false);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
bool isXz = std::memcmp(buf.Data(), XZ_MAGIC, 6) == 0;
|
|
49
|
+
return Napi::Boolean::New(env, isXz);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get liblzma version string (runtime).
|
|
54
|
+
* @returns Version string like "5.4.1"
|
|
55
|
+
*/
|
|
56
|
+
Napi::Value VersionString(const Napi::CallbackInfo &info)
|
|
57
|
+
{
|
|
58
|
+
Napi::Env env = info.Env();
|
|
59
|
+
return Napi::String::New(env, lzma_version_string());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get liblzma version number (runtime).
|
|
64
|
+
* @returns Version as integer (e.g., 50040010 for 5.4.1)
|
|
65
|
+
*/
|
|
66
|
+
Napi::Value VersionNumber(const Napi::CallbackInfo &info)
|
|
67
|
+
{
|
|
68
|
+
Napi::Env env = info.Env();
|
|
69
|
+
return Napi::Number::New(env, static_cast<double>(lzma_version_number()));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get memory usage for easy encoder with given preset.
|
|
74
|
+
* @param info[0] Preset level (0-9, optionally OR'd with LZMA_PRESET_EXTREME)
|
|
75
|
+
* @returns Memory usage in bytes, or 0 if preset is invalid
|
|
76
|
+
*/
|
|
77
|
+
Napi::Value EasyEncoderMemusage(const Napi::CallbackInfo &info)
|
|
78
|
+
{
|
|
79
|
+
Napi::Env env = info.Env();
|
|
80
|
+
|
|
81
|
+
if (info.Length() < 1 || !info[0].IsNumber())
|
|
82
|
+
{
|
|
83
|
+
Napi::TypeError::New(env, "Expected a preset number argument").ThrowAsJavaScriptException();
|
|
84
|
+
return env.Null();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
uint32_t preset = info[0].As<Napi::Number>().Uint32Value();
|
|
88
|
+
uint64_t memusage = lzma_easy_encoder_memusage(preset);
|
|
89
|
+
|
|
90
|
+
return Napi::Number::New(env, static_cast<double>(memusage));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get memory usage for easy decoder.
|
|
95
|
+
* @returns Memory usage in bytes
|
|
96
|
+
*/
|
|
97
|
+
Napi::Value EasyDecoderMemusage(const Napi::CallbackInfo &info)
|
|
98
|
+
{
|
|
99
|
+
Napi::Env env = info.Env();
|
|
100
|
+
|
|
101
|
+
// lzma_easy_decoder_memusage takes a preset for memlimit estimation
|
|
102
|
+
// but the actual decoder doesn't need a preset. Use default preset.
|
|
103
|
+
uint64_t memusage = lzma_easy_decoder_memusage(LZMA_PRESET_DEFAULT);
|
|
104
|
+
|
|
105
|
+
return Napi::Number::New(env, static_cast<double>(memusage));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Parse the Stream Footer and Index from an XZ file to get metadata.
|
|
110
|
+
* @param info[0] Buffer containing the XZ file (must be complete)
|
|
111
|
+
* @returns Object with uncompressed_size, compressed_size, stream_count, block_count, check
|
|
112
|
+
*/
|
|
113
|
+
Napi::Value ParseFileIndex(const Napi::CallbackInfo &info)
|
|
114
|
+
{
|
|
115
|
+
Napi::Env env = info.Env();
|
|
116
|
+
|
|
117
|
+
if (info.Length() < 1 || !info[0].IsBuffer())
|
|
118
|
+
{
|
|
119
|
+
Napi::TypeError::New(env, "Expected a Buffer argument").ThrowAsJavaScriptException();
|
|
120
|
+
return env.Null();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
Napi::Buffer<uint8_t> buf = info[0].As<Napi::Buffer<uint8_t>>();
|
|
124
|
+
const uint8_t *data = buf.Data();
|
|
125
|
+
size_t size = buf.Length();
|
|
126
|
+
|
|
127
|
+
// Minimum XZ file: header (12) + block (varies) + index (varies) + footer (12)
|
|
128
|
+
// Stream header is 12 bytes, footer is 12 bytes
|
|
129
|
+
if (size < LZMA_STREAM_HEADER_SIZE * 2)
|
|
130
|
+
{
|
|
131
|
+
Napi::Error::New(env, "Buffer too small for XZ stream").ThrowAsJavaScriptException();
|
|
132
|
+
return env.Null();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Verify XZ magic
|
|
136
|
+
if (std::memcmp(data, XZ_MAGIC, 6) != 0)
|
|
137
|
+
{
|
|
138
|
+
Napi::Error::New(env, "Not an XZ stream (invalid magic)").ThrowAsJavaScriptException();
|
|
139
|
+
return env.Null();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Parse stream header
|
|
143
|
+
lzma_stream_flags header_flags;
|
|
144
|
+
lzma_ret ret = lzma_stream_header_decode(&header_flags, data);
|
|
145
|
+
if (ret != LZMA_OK)
|
|
146
|
+
{
|
|
147
|
+
Napi::Error::New(env, "Failed to decode stream header").ThrowAsJavaScriptException();
|
|
148
|
+
return env.Null();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Parse stream footer (last 12 bytes)
|
|
152
|
+
lzma_stream_flags footer_flags;
|
|
153
|
+
ret = lzma_stream_footer_decode(&footer_flags, data + size - LZMA_STREAM_HEADER_SIZE);
|
|
154
|
+
if (ret != LZMA_OK)
|
|
155
|
+
{
|
|
156
|
+
Napi::Error::New(env, "Failed to decode stream footer").ThrowAsJavaScriptException();
|
|
157
|
+
return env.Null();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Verify header and footer match
|
|
161
|
+
ret = lzma_stream_flags_compare(&header_flags, &footer_flags);
|
|
162
|
+
if (ret != LZMA_OK)
|
|
163
|
+
{
|
|
164
|
+
Napi::Error::New(env, "Stream header and footer do not match").ThrowAsJavaScriptException();
|
|
165
|
+
return env.Null();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Calculate index position: footer starts at (size - 12), index is backward_size bytes before that
|
|
169
|
+
size_t footer_pos = size - LZMA_STREAM_HEADER_SIZE;
|
|
170
|
+
size_t index_size = footer_flags.backward_size;
|
|
171
|
+
|
|
172
|
+
if (index_size > footer_pos - LZMA_STREAM_HEADER_SIZE)
|
|
173
|
+
{
|
|
174
|
+
Napi::Error::New(env, "Invalid index size in footer").ThrowAsJavaScriptException();
|
|
175
|
+
return env.Null();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
size_t index_pos = footer_pos - index_size;
|
|
179
|
+
|
|
180
|
+
// Decode the index
|
|
181
|
+
lzma_index *index = nullptr;
|
|
182
|
+
uint64_t memlimit = UINT64_MAX;
|
|
183
|
+
size_t in_pos = 0;
|
|
184
|
+
|
|
185
|
+
ret = lzma_index_buffer_decode(&index, &memlimit, nullptr,
|
|
186
|
+
data + index_pos, &in_pos, index_size);
|
|
187
|
+
if (ret != LZMA_OK || index == nullptr)
|
|
188
|
+
{
|
|
189
|
+
Napi::Error::New(env, "Failed to decode index").ThrowAsJavaScriptException();
|
|
190
|
+
return env.Null();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Extract metadata from index
|
|
194
|
+
Napi::Object result = Napi::Object::New(env);
|
|
195
|
+
result.Set("uncompressedSize", Napi::Number::New(env, static_cast<double>(lzma_index_uncompressed_size(index))));
|
|
196
|
+
result.Set("compressedSize", Napi::Number::New(env, static_cast<double>(lzma_index_total_size(index))));
|
|
197
|
+
result.Set("streamCount", Napi::Number::New(env, static_cast<double>(lzma_index_stream_count(index))));
|
|
198
|
+
result.Set("blockCount", Napi::Number::New(env, static_cast<double>(lzma_index_block_count(index))));
|
|
199
|
+
result.Set("check", Napi::Number::New(env, static_cast<double>(footer_flags.check)));
|
|
200
|
+
result.Set("memoryUsage", Napi::Number::New(env, static_cast<double>(lzma_index_memused(index))));
|
|
201
|
+
|
|
202
|
+
// Clean up
|
|
203
|
+
lzma_index_end(index, nullptr);
|
|
204
|
+
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
20
207
|
|
|
21
208
|
Napi::Object Init(Napi::Env env, Napi::Object exports)
|
|
22
209
|
{
|
|
@@ -101,6 +288,15 @@ Napi::Object Init(Napi::Env env, Napi::Object exports)
|
|
|
101
288
|
|
|
102
289
|
// Tell companion script if we are thread-able or not
|
|
103
290
|
exports.Set(Napi::String::New(env, "HAS_THREADS_SUPPORT"), Napi::Boolean::New(env, HAS_THREADS_SUPPORT));
|
|
291
|
+
|
|
292
|
+
// Utility functions
|
|
293
|
+
exports.Set(Napi::String::New(env, "isXZ"), Napi::Function::New(env, IsXZ));
|
|
294
|
+
exports.Set(Napi::String::New(env, "versionString"), Napi::Function::New(env, VersionString));
|
|
295
|
+
exports.Set(Napi::String::New(env, "versionNumber"), Napi::Function::New(env, VersionNumber));
|
|
296
|
+
exports.Set(Napi::String::New(env, "easyEncoderMemusage"), Napi::Function::New(env, EasyEncoderMemusage));
|
|
297
|
+
exports.Set(Napi::String::New(env, "easyDecoderMemusage"), Napi::Function::New(env, EasyDecoderMemusage));
|
|
298
|
+
exports.Set(Napi::String::New(env, "parseFileIndex"), Napi::Function::New(env, ParseFileIndex));
|
|
299
|
+
|
|
104
300
|
return exports;
|
|
105
301
|
}
|
|
106
302
|
|