-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdecompress.ts
More file actions
88 lines (78 loc) · 3.07 KB
/
Copy pathdecompress.ts
File metadata and controls
88 lines (78 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
* @module cli/commands/decompress
*
* `text-compress` decompress path — decode and restore text or folder payloads.
*/
import { writeFileSync } from "node:fs"
import { unpackDirectory } from "../../archive/unpack.js"
import { decompressPayload, TAG_FOLDER, TAG_TEXT } from "../../payload/tags.js"
import { readSplitInput } from "../../split/parts.js"
import { formatBytes, formatCount, printRunSummary } from "../analytics.js"
import { type Args, readInput, resolveEncoding, resolveEncodingOptional } from "../args.js"
import { resolveDetectedEncoding } from "../detect.js"
import { resolveOutputPath } from "../paths.js"
/** Read compressed input from file (with split support) or inline text. */
function readCompressedInput(args: Args): {
content: string
inputBytes: number
partPaths?: string[]
} {
if (args.file) {
const { content, partPaths } = readSplitInput(args.file)
return {
content,
inputBytes: Buffer.byteLength(content, "utf-8"),
partPaths: partPaths.length > 1 ? partPaths : undefined,
}
}
const content = readInput(args)
return { content, inputBytes: Buffer.byteLength(content, "utf-8") }
}
/** Execute the decompress subcommand. */
export function runDecompress(args: Args): void {
const { content: input, inputBytes, partPaths } = readCompressedInput(args)
const encoding = resolveEncodingOptional(args)
? resolveEncoding(args)
: resolveDetectedEncoding(input, undefined, args.password)
const start = process.hrtime.bigint()
const { tag, data } = decompressPayload(input.trim(), encoding, args.password)
const elapsedMs = Number(process.hrtime.bigint() - start) / 1e6
if (tag === TAG_FOLDER) {
const outputPath = resolveOutputPath(args, "decompressed.de", ".de")
const { files, dirs, bytes } = unpackDirectory(data, outputPath)
printRunSummary({
title: "Decompressed folder",
outputPaths: [outputPath],
stats: {
Encoding: `base${encoding}`,
[`Compressed (base${encoding})`]: formatBytes(inputBytes),
...(partPaths ? { "Input parts": partPaths.length } : {}),
"Files restored": formatCount(files),
"Directories restored": formatCount(dirs),
"Restored size": formatBytes(bytes),
Time: `${elapsedMs.toFixed(0)} ms`,
},
})
return
}
if (tag !== TAG_TEXT) {
throw new Error(`Corrupt or unrecognized payload (tag 0x${tag.toString(16)}).`)
}
const outputPath = resolveOutputPath(args, "decompressed.de.txt", ".de.txt")
const result = data.toString("utf-8")
writeFileSync(outputPath, result, "utf-8")
const outputBytes = Buffer.byteLength(result, "utf-8")
const ratio = inputBytes === 0 ? 0 : outputBytes / inputBytes
printRunSummary({
title: "Decompressed text",
outputPaths: [outputPath],
stats: {
Encoding: `base${encoding}`,
[`Compressed (base${encoding})`]: formatBytes(inputBytes),
...(partPaths ? { "Input parts": partPaths.length } : {}),
"Restored size": formatBytes(outputBytes),
"Expansion ratio": ratio.toFixed(3),
Time: `${elapsedMs.toFixed(0)} ms`,
},
})
}