roxify 1.13.1 → 1.13.3
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/Cargo.toml +2 -11
- package/README.md +22 -144
- package/dist/cli.js +15 -20
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/rox-macos-universal +0 -0
- package/dist/roxify_native +0 -0
- package/dist/roxify_native-macos-arm64 +0 -0
- package/dist/roxify_native-macos-x64 +0 -0
- package/dist/roxify_native.exe +0 -0
- package/dist/utils/rust-cli-wrapper.d.ts +3 -2
- package/dist/utils/rust-cli-wrapper.js +26 -6
- package/native/bench_hybrid.rs +1 -1
- package/native/core.rs +3 -48
- package/native/crypto.rs +5 -0
- package/native/encoder.rs +10 -228
- package/native/hybrid.rs +17 -7
- package/native/lib.rs +54 -65
- package/native/main.rs +20 -3
- package/native/progress.rs +117 -18
- package/native/streaming_decode.rs +91 -7
- package/native/streaming_encode.rs +77 -50
- package/package.json +1 -1
- package/roxify_native-aarch64-apple-darwin.node +0 -0
- package/roxify_native-aarch64-pc-windows-msvc.node +0 -0
- package/roxify_native-aarch64-unknown-linux-gnu.node +0 -0
- package/roxify_native-i686-pc-windows-msvc.node +0 -0
- package/roxify_native-i686-unknown-linux-gnu.node +0 -0
- package/roxify_native-x86_64-apple-darwin.node +0 -0
- package/roxify_native-x86_64-pc-windows-msvc.node +0 -0
- package/roxify_native-x86_64-unknown-linux-gnu.node +0 -0
- package/dist/roxify-cli +0 -0
- package/libroxify_native-x86_64-unknown-linux-gnu.node +0 -0
- package/native/gpu.rs +0 -116
package/native/lib.rs
CHANGED
|
@@ -6,8 +6,6 @@ use napi_derive::napi;
|
|
|
6
6
|
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
|
7
7
|
|
|
8
8
|
mod core;
|
|
9
|
-
#[cfg(feature = "gpu")]
|
|
10
|
-
mod gpu;
|
|
11
9
|
mod rans;
|
|
12
10
|
mod rans_byte;
|
|
13
11
|
mod bwt;
|
|
@@ -27,15 +25,6 @@ mod archive;
|
|
|
27
25
|
mod streaming;
|
|
28
26
|
|
|
29
27
|
pub use core::*;
|
|
30
|
-
#[cfg(feature = "gpu")]
|
|
31
|
-
pub use gpu::*;
|
|
32
|
-
#[cfg(not(feature = "gpu"))]
|
|
33
|
-
mod gpu {
|
|
34
|
-
pub fn gpu_available() -> bool {
|
|
35
|
-
false
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
28
|
pub use rans::*;
|
|
40
29
|
pub use bwt::*;
|
|
41
30
|
pub use context_mixing::*;
|
|
@@ -57,12 +46,6 @@ pub struct CompressionReport {
|
|
|
57
46
|
pub blocks_count: u32,
|
|
58
47
|
}
|
|
59
48
|
|
|
60
|
-
#[napi(object)]
|
|
61
|
-
pub struct GpuStatus {
|
|
62
|
-
pub available: bool,
|
|
63
|
-
pub adapter_info: Option<String>,
|
|
64
|
-
}
|
|
65
|
-
|
|
66
49
|
#[cfg(not(test))]
|
|
67
50
|
#[napi]
|
|
68
51
|
pub fn scan_pixels(buffer: Buffer, channels: u32, marker_bytes: Option<Buffer>) -> Result<ScanResult> {
|
|
@@ -86,60 +69,51 @@ pub fn native_adler32(buffer: Buffer) -> u32 {
|
|
|
86
69
|
|
|
87
70
|
#[cfg(not(test))]
|
|
88
71
|
#[napi]
|
|
89
|
-
pub fn native_delta_encode(buffer: Buffer) ->
|
|
90
|
-
core::delta_encode_bytes(&buffer)
|
|
72
|
+
pub fn native_delta_encode(buffer: Buffer) -> Buffer {
|
|
73
|
+
core::delta_encode_bytes(&buffer).into()
|
|
91
74
|
}
|
|
92
75
|
|
|
93
76
|
#[cfg(not(test))]
|
|
94
77
|
#[napi]
|
|
95
|
-
pub fn native_delta_decode(buffer: Buffer) ->
|
|
96
|
-
core::delta_decode_bytes(&buffer)
|
|
78
|
+
pub fn native_delta_decode(buffer: Buffer) -> Buffer {
|
|
79
|
+
core::delta_decode_bytes(&buffer).into()
|
|
97
80
|
}
|
|
98
81
|
|
|
99
82
|
#[cfg(not(test))]
|
|
100
83
|
#[napi]
|
|
101
|
-
pub fn native_zstd_compress(buffer: Buffer, level: i32) -> Result<
|
|
102
|
-
core::zstd_compress_bytes(&buffer, level, None).map_err(|e| Error::from_reason(e))
|
|
84
|
+
pub fn native_zstd_compress(buffer: Buffer, level: i32) -> Result<Buffer> {
|
|
85
|
+
core::zstd_compress_bytes(&buffer, level, None).map(Buffer::from).map_err(|e| Error::from_reason(e))
|
|
103
86
|
}
|
|
104
87
|
|
|
105
88
|
#[cfg(not(test))]
|
|
106
89
|
#[napi]
|
|
107
|
-
pub fn native_zstd_compress_with_dict(buffer: Buffer, level: i32, dict: Buffer) -> Result<
|
|
90
|
+
pub fn native_zstd_compress_with_dict(buffer: Buffer, level: i32, dict: Buffer) -> Result<Buffer> {
|
|
108
91
|
let dict_slice: &[u8] = &dict;
|
|
109
|
-
core::zstd_compress_bytes(&buffer, level, Some(dict_slice)).map_err(|e| Error::from_reason(e))
|
|
92
|
+
core::zstd_compress_bytes(&buffer, level, Some(dict_slice)).map(Buffer::from).map_err(|e| Error::from_reason(e))
|
|
110
93
|
}
|
|
111
94
|
|
|
112
95
|
#[cfg(not(test))]
|
|
113
96
|
#[napi]
|
|
114
|
-
pub fn native_zstd_decompress(buffer: Buffer) -> Result<
|
|
115
|
-
core::zstd_decompress_bytes(&buffer, None).map_err(|e| Error::from_reason(e))
|
|
97
|
+
pub fn native_zstd_decompress(buffer: Buffer) -> Result<Buffer> {
|
|
98
|
+
core::zstd_decompress_bytes(&buffer, None).map(Buffer::from).map_err(|e| Error::from_reason(e))
|
|
116
99
|
}
|
|
117
100
|
|
|
118
101
|
#[cfg(not(test))]
|
|
119
102
|
#[napi]
|
|
120
|
-
pub fn native_zstd_decompress_with_dict(buffer: Buffer, dict: Buffer) -> Result<
|
|
103
|
+
pub fn native_zstd_decompress_with_dict(buffer: Buffer, dict: Buffer) -> Result<Buffer> {
|
|
121
104
|
let dict_slice: &[u8] = &dict;
|
|
122
|
-
core::zstd_decompress_bytes(&buffer, Some(dict_slice)).map_err(|e| Error::from_reason(e))
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
#[cfg(not(test))]
|
|
126
|
-
#[napi]
|
|
127
|
-
pub fn check_gpu_status() -> GpuStatus {
|
|
128
|
-
GpuStatus {
|
|
129
|
-
available: gpu::gpu_available(),
|
|
130
|
-
adapter_info: None,
|
|
131
|
-
}
|
|
105
|
+
core::zstd_decompress_bytes(&buffer, Some(dict_slice)).map(Buffer::from).map_err(|e| Error::from_reason(e))
|
|
132
106
|
}
|
|
133
107
|
|
|
134
108
|
#[cfg(not(test))]
|
|
135
109
|
#[napi]
|
|
136
|
-
pub fn bwt_transform(buffer: Buffer) -> Result<
|
|
110
|
+
pub fn bwt_transform(buffer: Buffer) -> Result<Buffer> {
|
|
137
111
|
match bwt::bwt_encode(&buffer) {
|
|
138
112
|
Ok(result) => {
|
|
139
113
|
let mut output = Vec::with_capacity(4 + result.transformed.len());
|
|
140
114
|
output.extend_from_slice(&result.primary_index.to_le_bytes());
|
|
141
115
|
output.extend_from_slice(&result.transformed);
|
|
142
|
-
Ok(output)
|
|
116
|
+
Ok(output.into())
|
|
143
117
|
}
|
|
144
118
|
Err(e) => Err(Error::from_reason(e.to_string())),
|
|
145
119
|
}
|
|
@@ -217,15 +191,17 @@ mod tests {
|
|
|
217
191
|
|
|
218
192
|
#[cfg(not(test))]
|
|
219
193
|
#[napi]
|
|
220
|
-
pub fn native_encode_png(buffer: Buffer, compression_level: i32) -> Result<
|
|
194
|
+
pub fn native_encode_png(buffer: Buffer, compression_level: i32) -> Result<Buffer> {
|
|
221
195
|
encoder::encode_to_png(&buffer, compression_level)
|
|
196
|
+
.map(Buffer::from)
|
|
222
197
|
.map_err(|e| Error::from_reason(e.to_string()))
|
|
223
198
|
}
|
|
224
199
|
|
|
225
200
|
#[cfg(not(test))]
|
|
226
201
|
#[napi]
|
|
227
|
-
pub fn native_encode_png_raw(buffer: Buffer, compression_level: i32) -> Result<
|
|
202
|
+
pub fn native_encode_png_raw(buffer: Buffer, compression_level: i32) -> Result<Buffer> {
|
|
228
203
|
encoder::encode_to_png_raw(&buffer, compression_level)
|
|
204
|
+
.map(Buffer::from)
|
|
229
205
|
.map_err(|e| Error::from_reason(e.to_string()))
|
|
230
206
|
}
|
|
231
207
|
|
|
@@ -236,13 +212,14 @@ pub fn native_encode_png_with_name_and_filelist(
|
|
|
236
212
|
compression_level: i32,
|
|
237
213
|
name: Option<String>,
|
|
238
214
|
file_list_json: Option<String>,
|
|
239
|
-
) -> Result<
|
|
215
|
+
) -> Result<Buffer> {
|
|
240
216
|
encoder::encode_to_png_with_name_and_filelist(
|
|
241
217
|
&buffer,
|
|
242
218
|
compression_level,
|
|
243
219
|
name.as_deref(),
|
|
244
220
|
file_list_json.as_deref(),
|
|
245
221
|
)
|
|
222
|
+
.map(Buffer::from)
|
|
246
223
|
.map_err(|e| Error::from_reason(e.to_string()))
|
|
247
224
|
}
|
|
248
225
|
|
|
@@ -255,7 +232,7 @@ pub fn native_encode_png_with_encryption_name_and_filelist(
|
|
|
255
232
|
encrypt_type: Option<String>,
|
|
256
233
|
name: Option<String>,
|
|
257
234
|
file_list_json: Option<String>,
|
|
258
|
-
) -> Result<
|
|
235
|
+
) -> Result<Buffer> {
|
|
259
236
|
encoder::encode_to_png_with_encryption_name_and_filelist(
|
|
260
237
|
&buffer,
|
|
261
238
|
compression_level,
|
|
@@ -264,13 +241,14 @@ pub fn native_encode_png_with_encryption_name_and_filelist(
|
|
|
264
241
|
name.as_deref(),
|
|
265
242
|
file_list_json.as_deref(),
|
|
266
243
|
)
|
|
244
|
+
.map(Buffer::from)
|
|
267
245
|
.map_err(|e| Error::from_reason(e.to_string()))
|
|
268
246
|
}
|
|
269
247
|
|
|
270
248
|
#[napi(object)]
|
|
271
249
|
pub struct PngChunkData {
|
|
272
250
|
pub name: String,
|
|
273
|
-
pub data:
|
|
251
|
+
pub data: Buffer,
|
|
274
252
|
}
|
|
275
253
|
|
|
276
254
|
#[cfg(not(test))]
|
|
@@ -281,21 +259,22 @@ pub fn extract_png_chunks(png_buffer: Buffer) -> Result<Vec<PngChunkData>> {
|
|
|
281
259
|
|
|
282
260
|
Ok(chunks.into_iter().map(|c| PngChunkData {
|
|
283
261
|
name: c.name,
|
|
284
|
-
data: c.data,
|
|
262
|
+
data: c.data.into(),
|
|
285
263
|
}).collect())
|
|
286
264
|
}
|
|
287
265
|
|
|
288
266
|
#[cfg(not(test))]
|
|
289
267
|
#[napi]
|
|
290
|
-
pub fn encode_png_chunks(chunks: Vec<PngChunkData>) -> Result<
|
|
268
|
+
pub fn encode_png_chunks(chunks: Vec<PngChunkData>) -> Result<Buffer> {
|
|
291
269
|
let native_chunks: Vec<png_utils::PngChunk> = chunks.into_iter()
|
|
292
270
|
.map(|c| png_utils::PngChunk {
|
|
293
271
|
name: c.name,
|
|
294
|
-
data: c.data,
|
|
272
|
+
data: c.data.to_vec(),
|
|
295
273
|
})
|
|
296
274
|
.collect();
|
|
297
275
|
|
|
298
276
|
png_utils::encode_png_chunks(&native_chunks)
|
|
277
|
+
.map(Buffer::from)
|
|
299
278
|
.map_err(|e| Error::from_reason(e))
|
|
300
279
|
}
|
|
301
280
|
|
|
@@ -335,22 +314,23 @@ pub fn sharp_resize_image(
|
|
|
335
314
|
width: u32,
|
|
336
315
|
height: u32,
|
|
337
316
|
kernel: String,
|
|
338
|
-
) -> Result<
|
|
317
|
+
) -> Result<Buffer> {
|
|
339
318
|
image_utils::sharp_resize(&input_buffer, width, height, &kernel)
|
|
319
|
+
.map(Buffer::from)
|
|
340
320
|
.map_err(|e| Error::from_reason(e))
|
|
341
321
|
}
|
|
342
322
|
|
|
343
323
|
#[cfg(not(test))]
|
|
344
324
|
#[napi]
|
|
345
|
-
pub fn sharp_raw_pixels(input_buffer: Buffer) -> Result<
|
|
325
|
+
pub fn sharp_raw_pixels(input_buffer: Buffer) -> Result<Buffer> {
|
|
346
326
|
let (pixels, _w, _h) = image_utils::sharp_raw_pixels(&input_buffer)
|
|
347
327
|
.map_err(|e| Error::from_reason(e))?;
|
|
348
|
-
Ok(pixels)
|
|
328
|
+
Ok(pixels.into())
|
|
349
329
|
}
|
|
350
330
|
|
|
351
331
|
#[napi(object)]
|
|
352
332
|
pub struct RawPixelsWithDimensions {
|
|
353
|
-
pub pixels:
|
|
333
|
+
pub pixels: Buffer,
|
|
354
334
|
pub width: u32,
|
|
355
335
|
pub height: u32,
|
|
356
336
|
}
|
|
@@ -360,7 +340,7 @@ pub struct RawPixelsWithDimensions {
|
|
|
360
340
|
pub fn sharp_to_raw(input_buffer: Buffer) -> Result<RawPixelsWithDimensions> {
|
|
361
341
|
let (pixels, width, height) = image_utils::sharp_raw_pixels(&input_buffer)
|
|
362
342
|
.map_err(|e| Error::from_reason(e))?;
|
|
363
|
-
Ok(RawPixelsWithDimensions { pixels, width, height })
|
|
343
|
+
Ok(RawPixelsWithDimensions { pixels: pixels.into(), width, height })
|
|
364
344
|
}
|
|
365
345
|
|
|
366
346
|
#[cfg(not(test))]
|
|
@@ -373,8 +353,9 @@ pub fn sharp_metadata(input_buffer: Buffer) -> Result<SharpMetadata> {
|
|
|
373
353
|
|
|
374
354
|
#[cfg(not(test))]
|
|
375
355
|
#[napi]
|
|
376
|
-
pub fn rgb_to_png(rgb_buffer: Buffer, width: u32, height: u32) -> Result<
|
|
356
|
+
pub fn rgb_to_png(rgb_buffer: Buffer, width: u32, height: u32) -> Result<Buffer> {
|
|
377
357
|
image_utils::rgb_to_png(&rgb_buffer, width, height)
|
|
358
|
+
.map(Buffer::from)
|
|
378
359
|
.map_err(|e| Error::from_reason(e))
|
|
379
360
|
}
|
|
380
361
|
|
|
@@ -383,27 +364,30 @@ pub fn rgb_to_png(rgb_buffer: Buffer, width: u32, height: u32) -> Result<Vec<u8>
|
|
|
383
364
|
pub fn png_to_rgb(png_buffer: Buffer) -> Result<RawPixelsWithDimensions> {
|
|
384
365
|
let (pixels, width, height) = image_utils::png_to_rgb(&png_buffer)
|
|
385
366
|
.map_err(|e| Error::from_reason(e))?;
|
|
386
|
-
Ok(RawPixelsWithDimensions { pixels, width, height })
|
|
367
|
+
Ok(RawPixelsWithDimensions { pixels: pixels.into(), width, height })
|
|
387
368
|
}
|
|
388
369
|
|
|
389
370
|
#[cfg(not(test))]
|
|
390
371
|
#[napi]
|
|
391
|
-
pub fn crop_and_reconstitute(png_buffer: Buffer) -> Result<
|
|
372
|
+
pub fn crop_and_reconstitute(png_buffer: Buffer) -> Result<Buffer> {
|
|
392
373
|
reconstitution::crop_and_reconstitute(&png_buffer)
|
|
374
|
+
.map(Buffer::from)
|
|
393
375
|
.map_err(|e| Error::from_reason(e))
|
|
394
376
|
}
|
|
395
377
|
|
|
396
378
|
#[cfg(not(test))]
|
|
397
379
|
#[napi]
|
|
398
|
-
pub fn unstretch_nn(png_buffer: Buffer) -> Result<
|
|
380
|
+
pub fn unstretch_nn(png_buffer: Buffer) -> Result<Buffer> {
|
|
399
381
|
reconstitution::unstretch_nn(&png_buffer)
|
|
382
|
+
.map(Buffer::from)
|
|
400
383
|
.map_err(|e| Error::from_reason(e))
|
|
401
384
|
}
|
|
402
385
|
|
|
403
386
|
#[cfg(not(test))]
|
|
404
387
|
#[napi]
|
|
405
|
-
pub fn extract_payload_from_png(png_buffer: Buffer) -> Result<
|
|
388
|
+
pub fn extract_payload_from_png(png_buffer: Buffer) -> Result<Buffer> {
|
|
406
389
|
png_utils::extract_payload_from_png(&png_buffer)
|
|
390
|
+
.map(Buffer::from)
|
|
407
391
|
.map_err(|e| Error::from_reason(e))
|
|
408
392
|
}
|
|
409
393
|
|
|
@@ -418,8 +402,9 @@ pub fn extract_file_list_from_pixels(png_buffer: Buffer) -> Result<String> {
|
|
|
418
402
|
|
|
419
403
|
#[cfg(not(test))]
|
|
420
404
|
#[napi]
|
|
421
|
-
pub fn native_encode_wav(buffer: Buffer, compression_level: i32) -> Result<
|
|
405
|
+
pub fn native_encode_wav(buffer: Buffer, compression_level: i32) -> Result<Buffer> {
|
|
422
406
|
encoder::encode_to_wav(&buffer, compression_level)
|
|
407
|
+
.map(Buffer::from)
|
|
423
408
|
.map_err(|e| Error::from_reason(e.to_string()))
|
|
424
409
|
}
|
|
425
410
|
|
|
@@ -430,13 +415,14 @@ pub fn native_encode_wav_with_name_and_filelist(
|
|
|
430
415
|
compression_level: i32,
|
|
431
416
|
name: Option<String>,
|
|
432
417
|
file_list_json: Option<String>,
|
|
433
|
-
) -> Result<
|
|
418
|
+
) -> Result<Buffer> {
|
|
434
419
|
encoder::encode_to_wav_with_name_and_filelist(
|
|
435
420
|
&buffer,
|
|
436
421
|
compression_level,
|
|
437
422
|
name.as_deref(),
|
|
438
423
|
file_list_json.as_deref(),
|
|
439
424
|
)
|
|
425
|
+
.map(Buffer::from)
|
|
440
426
|
.map_err(|e| Error::from_reason(e.to_string()))
|
|
441
427
|
}
|
|
442
428
|
|
|
@@ -449,7 +435,7 @@ pub fn native_encode_wav_with_encryption_name_and_filelist(
|
|
|
449
435
|
encrypt_type: Option<String>,
|
|
450
436
|
name: Option<String>,
|
|
451
437
|
file_list_json: Option<String>,
|
|
452
|
-
) -> Result<
|
|
438
|
+
) -> Result<Buffer> {
|
|
453
439
|
encoder::encode_to_wav_with_encryption_name_and_filelist(
|
|
454
440
|
&buffer,
|
|
455
441
|
compression_level,
|
|
@@ -458,26 +444,29 @@ pub fn native_encode_wav_with_encryption_name_and_filelist(
|
|
|
458
444
|
name.as_deref(),
|
|
459
445
|
file_list_json.as_deref(),
|
|
460
446
|
)
|
|
447
|
+
.map(Buffer::from)
|
|
461
448
|
.map_err(|e| Error::from_reason(e.to_string()))
|
|
462
449
|
}
|
|
463
450
|
|
|
464
451
|
#[cfg(not(test))]
|
|
465
452
|
#[napi]
|
|
466
|
-
pub fn native_decode_wav_payload(wav_buffer: Buffer) -> Result<
|
|
453
|
+
pub fn native_decode_wav_payload(wav_buffer: Buffer) -> Result<Buffer> {
|
|
467
454
|
encoder::decode_wav_payload(&wav_buffer)
|
|
455
|
+
.map(Buffer::from)
|
|
468
456
|
.map_err(|e| Error::from_reason(e.to_string()))
|
|
469
457
|
}
|
|
470
458
|
|
|
471
459
|
#[cfg(not(test))]
|
|
472
460
|
#[napi]
|
|
473
|
-
pub fn native_bytes_to_wav(buffer: Buffer) ->
|
|
474
|
-
audio::bytes_to_wav(&buffer)
|
|
461
|
+
pub fn native_bytes_to_wav(buffer: Buffer) -> Buffer {
|
|
462
|
+
audio::bytes_to_wav(&buffer).into()
|
|
475
463
|
}
|
|
476
464
|
|
|
477
465
|
#[cfg(not(test))]
|
|
478
466
|
#[napi]
|
|
479
|
-
pub fn native_wav_to_bytes(wav_buffer: Buffer) -> Result<
|
|
467
|
+
pub fn native_wav_to_bytes(wav_buffer: Buffer) -> Result<Buffer> {
|
|
480
468
|
audio::wav_to_bytes(&wav_buffer)
|
|
469
|
+
.map(Buffer::from)
|
|
481
470
|
.map_err(|e| Error::from_reason(e))
|
|
482
471
|
}
|
|
483
472
|
|
package/native/main.rs
CHANGED
|
@@ -17,6 +17,7 @@ mod archive;
|
|
|
17
17
|
mod streaming;
|
|
18
18
|
mod streaming_decode;
|
|
19
19
|
mod streaming_encode;
|
|
20
|
+
mod progress;
|
|
20
21
|
|
|
21
22
|
use crate::encoder::ImageFormat;
|
|
22
23
|
use std::path::PathBuf;
|
|
@@ -157,13 +158,16 @@ fn main() -> anyhow::Result<()> {
|
|
|
157
158
|
.or_else(|| input.file_name().and_then(|n| n.to_str()));
|
|
158
159
|
|
|
159
160
|
if is_dir && dict.is_none() {
|
|
160
|
-
streaming_encode::
|
|
161
|
+
streaming_encode::encode_dir_to_png_encrypted_with_progress(
|
|
161
162
|
&input,
|
|
162
163
|
&output,
|
|
163
164
|
level,
|
|
164
165
|
file_name,
|
|
165
166
|
passphrase.as_deref(),
|
|
166
167
|
Some(&encrypt),
|
|
168
|
+
Some(Box::new(|current, total, step| {
|
|
169
|
+
eprintln!("PROGRESS:{}:{}:{}", current, total, step);
|
|
170
|
+
})),
|
|
167
171
|
)?;
|
|
168
172
|
println!("(TAR archive, rXFL chunk embedded)");
|
|
169
173
|
return Ok(());
|
|
@@ -187,6 +191,7 @@ fn main() -> anyhow::Result<()> {
|
|
|
187
191
|
};
|
|
188
192
|
|
|
189
193
|
let use_streaming = payload.len() > 64 * 1024 * 1024;
|
|
194
|
+
eprintln!("PROGRESS:50:100:encoding");
|
|
190
195
|
|
|
191
196
|
if use_streaming {
|
|
192
197
|
streaming::encode_to_png_file(
|
|
@@ -227,6 +232,7 @@ fn main() -> anyhow::Result<()> {
|
|
|
227
232
|
}
|
|
228
233
|
|
|
229
234
|
if file_list_json.is_some() {
|
|
235
|
+
eprintln!("PROGRESS:100:100:done");
|
|
230
236
|
if is_dir {
|
|
231
237
|
println!("(TAR archive, rXFL chunk embedded)");
|
|
232
238
|
} else {
|
|
@@ -337,10 +343,18 @@ fn main() -> anyhow::Result<()> {
|
|
|
337
343
|
&& sig == [137, 80, 78, 71, 13, 10, 26, 10]
|
|
338
344
|
});
|
|
339
345
|
|
|
340
|
-
if is_png_file && files.is_none() && dict.is_none()
|
|
346
|
+
if is_png_file && files.is_none() && dict.is_none() {
|
|
341
347
|
let out_dir = output.clone().unwrap_or_else(|| PathBuf::from("out.raw"));
|
|
342
|
-
match streaming_decode::
|
|
348
|
+
match streaming_decode::streaming_decode_to_dir_encrypted_with_progress(
|
|
349
|
+
&input,
|
|
350
|
+
&out_dir,
|
|
351
|
+
passphrase.as_deref(),
|
|
352
|
+
Some(Box::new(|current, total, step| {
|
|
353
|
+
eprintln!("PROGRESS:{}:{}:{}", current, total, step);
|
|
354
|
+
})),
|
|
355
|
+
) {
|
|
343
356
|
Ok(written) => {
|
|
357
|
+
eprintln!("PROGRESS:100:100:done");
|
|
344
358
|
println!("Unpacked {} files (TAR)", written.len());
|
|
345
359
|
return Ok(());
|
|
346
360
|
}
|
|
@@ -351,6 +365,7 @@ fn main() -> anyhow::Result<()> {
|
|
|
351
365
|
}
|
|
352
366
|
|
|
353
367
|
let buf = read_all(&input)?;
|
|
368
|
+
eprintln!("PROGRESS:20:100:decompressing");
|
|
354
369
|
let dict_bytes: Option<Vec<u8>> = match dict {
|
|
355
370
|
Some(path) => Some(read_all(&path)?),
|
|
356
371
|
None => None,
|
|
@@ -413,6 +428,7 @@ fn main() -> anyhow::Result<()> {
|
|
|
413
428
|
let files_slice = file_list.as_ref().map(|v| v.as_slice());
|
|
414
429
|
|
|
415
430
|
let written = packer::unpack_stream_to_dir(&mut reader, &out_dir, files_slice).map_err(|e| anyhow::anyhow!(e))?;
|
|
431
|
+
eprintln!("PROGRESS:100:100:done");
|
|
416
432
|
println!("Unpacked {} files", written.len());
|
|
417
433
|
} else {
|
|
418
434
|
let is_png = buf.len() >= 8 && &buf[0..8] == &[137, 80, 78, 71, 13, 10, 26, 10];
|
|
@@ -511,6 +527,7 @@ fn main() -> anyhow::Result<()> {
|
|
|
511
527
|
} else {
|
|
512
528
|
write_all(&dest, &out_bytes)?;
|
|
513
529
|
}
|
|
530
|
+
eprintln!("PROGRESS:100:100:done");
|
|
514
531
|
}
|
|
515
532
|
}
|
|
516
533
|
Commands::Crc32 { input } => {
|
package/native/progress.rs
CHANGED
|
@@ -1,43 +1,142 @@
|
|
|
1
1
|
use parking_lot::Mutex;
|
|
2
2
|
use std::sync::Arc;
|
|
3
|
+
use std::time::Instant;
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
#[derive(Clone, Debug)]
|
|
6
|
+
pub struct ProgressSnapshot {
|
|
7
|
+
pub current: u64,
|
|
8
|
+
pub total: u64,
|
|
9
|
+
pub percentage: f64,
|
|
10
|
+
pub elapsed_ms: u64,
|
|
11
|
+
pub eta_ms: Option<u64>,
|
|
12
|
+
pub speed_bytes_per_sec: f64,
|
|
13
|
+
pub step: String,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
struct ProgressInner {
|
|
5
17
|
total: u64,
|
|
6
|
-
current:
|
|
7
|
-
|
|
18
|
+
current: u64,
|
|
19
|
+
step: String,
|
|
20
|
+
start: Instant,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
pub struct ProgressBar {
|
|
24
|
+
inner: Arc<Mutex<ProgressInner>>,
|
|
25
|
+
callback: Arc<Mutex<Option<Box<dyn Fn(ProgressSnapshot) + Send>>>>,
|
|
8
26
|
}
|
|
9
27
|
|
|
10
28
|
impl ProgressBar {
|
|
11
29
|
pub fn new(total: u64) -> Self {
|
|
12
30
|
Self {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
31
|
+
inner: Arc::new(Mutex::new(ProgressInner {
|
|
32
|
+
total,
|
|
33
|
+
current: 0,
|
|
34
|
+
step: String::new(),
|
|
35
|
+
start: Instant::now(),
|
|
36
|
+
})),
|
|
37
|
+
callback: Arc::new(Mutex::new(None)),
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
pub fn with_callback<F: Fn(ProgressSnapshot) + Send + 'static>(total: u64, cb: F) -> Self {
|
|
42
|
+
Self {
|
|
43
|
+
inner: Arc::new(Mutex::new(ProgressInner {
|
|
44
|
+
total,
|
|
45
|
+
current: 0,
|
|
46
|
+
step: String::new(),
|
|
47
|
+
start: Instant::now(),
|
|
48
|
+
})),
|
|
49
|
+
callback: Arc::new(Mutex::new(Some(Box::new(cb)))),
|
|
16
50
|
}
|
|
17
51
|
}
|
|
18
52
|
|
|
19
53
|
pub fn inc(&self, delta: u64) {
|
|
20
|
-
let
|
|
21
|
-
|
|
54
|
+
let snapshot = {
|
|
55
|
+
let mut inner = self.inner.lock();
|
|
56
|
+
inner.current += delta;
|
|
57
|
+
self.snapshot_inner(&inner)
|
|
58
|
+
};
|
|
59
|
+
self.emit(snapshot);
|
|
22
60
|
}
|
|
23
61
|
|
|
24
62
|
pub fn set(&self, value: u64) {
|
|
25
|
-
let
|
|
26
|
-
|
|
63
|
+
let snapshot = {
|
|
64
|
+
let mut inner = self.inner.lock();
|
|
65
|
+
inner.current = value;
|
|
66
|
+
self.snapshot_inner(&inner)
|
|
67
|
+
};
|
|
68
|
+
self.emit(snapshot);
|
|
27
69
|
}
|
|
28
70
|
|
|
29
|
-
pub fn
|
|
30
|
-
let
|
|
31
|
-
|
|
71
|
+
pub fn set_step(&self, step: &str) {
|
|
72
|
+
let snapshot = {
|
|
73
|
+
let mut inner = self.inner.lock();
|
|
74
|
+
inner.step = step.to_string();
|
|
75
|
+
self.snapshot_inner(&inner)
|
|
76
|
+
};
|
|
77
|
+
self.emit(snapshot);
|
|
32
78
|
}
|
|
33
79
|
|
|
34
|
-
pub fn
|
|
35
|
-
let
|
|
36
|
-
|
|
80
|
+
pub fn snapshot(&self) -> ProgressSnapshot {
|
|
81
|
+
let inner = self.inner.lock();
|
|
82
|
+
self.snapshot_inner(&inner)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
fn snapshot_inner(&self, inner: &ProgressInner) -> ProgressSnapshot {
|
|
86
|
+
let elapsed = inner.start.elapsed();
|
|
87
|
+
let elapsed_ms = elapsed.as_millis() as u64;
|
|
88
|
+
let percentage = if inner.total > 0 {
|
|
89
|
+
(inner.current as f64 / inner.total as f64) * 100.0
|
|
90
|
+
} else {
|
|
91
|
+
0.0
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
let elapsed_secs = elapsed.as_secs_f64();
|
|
95
|
+
let speed = if elapsed_secs > 0.01 {
|
|
96
|
+
inner.current as f64 / elapsed_secs
|
|
97
|
+
} else {
|
|
98
|
+
0.0
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
let eta_ms = if speed > 0.0 && inner.current > 0 && inner.current < inner.total {
|
|
102
|
+
let remaining = inner.total - inner.current;
|
|
103
|
+
Some((remaining as f64 / speed * 1000.0) as u64)
|
|
104
|
+
} else {
|
|
105
|
+
None
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
ProgressSnapshot {
|
|
109
|
+
current: inner.current,
|
|
110
|
+
total: inner.total,
|
|
111
|
+
percentage,
|
|
112
|
+
elapsed_ms,
|
|
113
|
+
eta_ms,
|
|
114
|
+
speed_bytes_per_sec: speed,
|
|
115
|
+
step: inner.step.clone(),
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
fn emit(&self, snapshot: ProgressSnapshot) {
|
|
120
|
+
if let Some(ref cb) = *self.callback.lock() {
|
|
121
|
+
cb(snapshot);
|
|
122
|
+
}
|
|
37
123
|
}
|
|
38
124
|
|
|
39
125
|
pub fn finish(&self) {
|
|
40
|
-
let
|
|
41
|
-
|
|
126
|
+
let snapshot = {
|
|
127
|
+
let mut inner = self.inner.lock();
|
|
128
|
+
inner.current = inner.total;
|
|
129
|
+
self.snapshot_inner(&inner)
|
|
130
|
+
};
|
|
131
|
+
self.emit(snapshot);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
pub fn get_progress(&self) -> (u64, u64) {
|
|
135
|
+
let inner = self.inner.lock();
|
|
136
|
+
(inner.current, inner.total)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
pub fn set_message(&self, msg: String) {
|
|
140
|
+
self.set_step(&msg);
|
|
42
141
|
}
|
|
43
142
|
}
|