Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LZMA Compress & Decompress operations #1421

Merged
merged 3 commits into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"@blu3r4y/lzma": "^2.3.3",
"arrive": "^2.4.1",
"avsc": "^5.7.4",
"bcryptjs": "^2.4.3",
Expand Down
4 changes: 3 additions & 1 deletion src/core/config/Categories.json
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,10 @@
"Bzip2 Compress",
"Tar",
"Untar",
"LZString Decompress",
"LZString Compress",
"LZString Decompress"
"LZMA Decompress",
"LZMA Compress"
]
},
{
Expand Down
64 changes: 64 additions & 0 deletions src/core/operations/LZMACompress.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* @author Matt C [me@mitt.dev]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/

import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";

import { compress } from "@blu3r4y/lzma";
import {isWorkerEnvironment} from "../Utils.mjs";

/**
* LZMA Compress operation
*/
class LZMACompress extends Operation {

/**
* LZMACompress constructor
*/
constructor() {
super();

this.name = "LZMA Compress";
this.module = "Compression";
this.description = "Compresses data using the Lempel\u2013Ziv\u2013Markov chain algorithm. Compression mode determines the speed and effectiveness of the compression: 1 is fastest and less effective, 9 is slowest and most effective";
this.infoURL = "https://wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Markov_chain_algorithm";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
this.args = [
{
name: "Compression Mode",
type: "option",
value: [
"1", "2", "3", "4", "5", "6", "7", "8", "9"
],
"defaultIndex": 6
}
];
}

/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
async run(input, args) {
const mode = Number(args[0]);
return new Promise((resolve, reject) => {
compress(new Uint8Array(input), mode, (result, error) => {
if (error) {
reject(new OperationError(`Failed to compress input: ${error.message}`));
}
// The compression returns as an Int8Array, but we can just get the unsigned data from the buffer
resolve(new Int8Array(result).buffer);
}, (percent) => {
if (isWorkerEnvironment()) self.sendStatusMessage(`Compressing input: ${(percent*100).toFixed(2)}%`);
});
});
}

}

export default LZMACompress;
57 changes: 57 additions & 0 deletions src/core/operations/LZMADecompress.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @author Matt C [me@mitt.dev]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/

import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import {decompress} from "@blu3r4y/lzma";
import Utils, {isWorkerEnvironment} from "../Utils.mjs";

/**
* LZMA Decompress operation
*/
class LZMADecompress extends Operation {

/**
* LZMADecompress constructor
*/
constructor() {
super();

this.name = "LZMA Decompress";
this.module = "Compression";
this.description = "Decompresses data using the Lempel-Ziv-Markov chain Algorithm.";
this.infoURL = "https://wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Markov_chain_algorithm";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
}

/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
async run(input, args) {
return new Promise((resolve, reject) => {
decompress(new Uint8Array(input), (result, error) => {
if (error) {
reject(new OperationError(`Failed to decompress input: ${error.message}`));
}
// The decompression returns either a String or an untyped unsigned int8 array, but we can just get the unsigned data from the buffer

if (typeof result == "string") {
resolve(Utils.strToArrayBuffer(result));
} else {
resolve(new Int8Array(result).buffer);
}
}, (percent) => {
if (isWorkerEnvironment()) self.sendStatusMessage(`Decompressing input: ${(percent*100).toFixed(2)}%`);
});
});
}

}

export default LZMADecompress;
52 changes: 52 additions & 0 deletions tests/operations/tests/Compress.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,56 @@ TestRegister.addTests([
}
],
},
{
name: "LZMA compress & decompress",
input: "The cat sat on the mat.",
// Generated using command `echo -n "The cat sat on the mat." | lzma -z -6 | xxd -p`
expectedOutput: "The cat sat on the mat.",
recipeConfig: [
{
"op": "LZMA Compress",
"args": ["6"]
},
{
"op": "LZMA Decompress",
"args": []
},
],
},
{
name: "LZMA decompress: binary",
// Generated using command `echo "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10" | xxd -r -p | lzma -z -6 | xxd -p`
input: "5d00008000ffffffffffffffff00000052500a84f99bb28021a969d627e03e8a922effffbd160000",
expectedOutput: "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10",
recipeConfig: [
{
"op": "From Hex",
"args": ["Space"]
},
{
"op": "LZMA Decompress",
"args": []
},
{
"op": "To Hex",
"args": ["Space", 0]
}
],
},
{
name: "LZMA decompress: string",
// Generated using command `echo -n "The cat sat on the mat." | lzma -z -6 | xxd -p`
input: "5d00008000ffffffffffffffff002a1a08a202b1a4b814b912c94c4152e1641907d3fd8cd903ffff4fec0000",
expectedOutput: "The cat sat on the mat.",
recipeConfig: [
{
"op": "From Hex",
"args": ["Space"]
},
{
"op": "LZMA Decompress",
"args": []
}
],
},
]);