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 named custom dictionary support #200

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
10 changes: 10 additions & 0 deletions src/__tests__/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,22 @@ exports[`index.ts > was the change deliberate? 1`] = `
"compressToUint8Array": [Function],
"convertFromUint8Array": [Function],
"convertToUint8Array": [Function],
"customBase16Dict": "0123456789ABCDEF",
"customBase32Dict": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
"customBase32HexDict": "0123456789ABCDEEFGHIJKLMNOPQRSTU",
"customBase36Dict": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"customBase58Dict": "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
"customBase62Dict": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
"customBase64Dict": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
"customBase95Dict": " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~",
"customSafeDict": " !#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~",
"decompress": [Function],
"decompressFromBase64": [Function],
"decompressFromCustom": [Function],
"decompressFromEncodedURIComponent": [Function],
"decompressFromUTF16": [Function],
"decompressFromUint8Array": [Function],
"getCustomDictionary": [Function],
"loadBinaryFile": [Function],
"saveBinaryFile": [Function],
}
Expand Down
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ program
.description("Use lz-string to compress or decompress a file")
.addOption(new Option("-d, --decompress", "if unset then this will compress"))
.addOption(new Option("-e, --encoder <type>", "character encoding to use").choices(encoders).default("raw"))
.addOption(new Option("-c, --custom", "dictionary for custom encoder"))
.addOption(new Option("-c, --custom <dict>", "dictionary for custom encoder"))
.addOption(new Option("-v, --verify", "verify before returning").default(true))
.addOption(new Option("-o, --output <output-file>", "output file, otherwise write to stdout"))
.addOption(new Option("-q, --quiet", "don't print any error messages"))
Expand Down
10 changes: 10 additions & 0 deletions src/custom/__tests__/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
exports[`custom/index.ts > was the change deliberate? 1`] = `
{
"compressToCustom": [Function],
"customBase16Dict": "0123456789ABCDEF",
"customBase32Dict": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
"customBase32HexDict": "0123456789ABCDEEFGHIJKLMNOPQRSTU",
"customBase36Dict": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"customBase58Dict": "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
"customBase62Dict": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
"customBase64Dict": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
"customBase95Dict": " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~",
"customSafeDict": " !#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~",
"decompressFromCustom": [Function],
"getCustomDictionary": [Function],
}
`;
5 changes: 2 additions & 3 deletions src/custom/__tests__/custom.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ describe("custom", () => {
});

describe("base62", () => {
const base62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const compress = (input: string | null) => compressToCustom(input, base62);
const decompress = (input: string | null) => decompressFromCustom(input, base62);
const compress = (input: string | null) => compressToCustom(input, "base62");
const decompress = (input: string | null) => decompressFromCustom(input, "base62");

runTestSet<string>("", compress, decompress);
});
Expand Down
9 changes: 9 additions & 0 deletions src/custom/compressToCustom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,19 @@
*/

import { compress } from "../raw/compress";
import { getCustomDictionary } from "./dictionaries";

/**
* Custom dictionary support, this is not ready for production use yet, so lock
* the versions if using.
*
* @alpha
*/
export function compressToCustom(uncompressed: string | null, dict: string): string {
if (uncompressed == null) return "";

dict = getCustomDictionary(dict);

const compressed: string = compress(uncompressed);
const charsPerUnicodeChar: number = Math.ceil(Math.log(65536) / Math.log(dict.length));
let res: string = "";
Expand Down
12 changes: 11 additions & 1 deletion src/custom/decompressFromCustom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,20 @@
*/

import { decompress } from "../raw/decompress";
import { getCustomDictionary } from "./dictionaries";

export function decompressFromCustom(compressed: string | null, dict: string): string | null {
/**
* Custom dictionary support, this is not ready for production use yet, so lock
* the versions if using.
*
* @alpha
*/
export function decompressFromCustom(compressed: string | null, dict: string) {
if (compressed == null) return "";
if (compressed == "") return null;

dict = getCustomDictionary(dict);

if (dict.length < 2) return null;

const charsPerUnicodeChar: number = Math.ceil(Math.log(65536) / Math.log(dict.length));
Expand Down
75 changes: 75 additions & 0 deletions src/custom/dictionaries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* SPDX-FileCopyrightText: 2013 Pieroxy <[email protected]>
*
* SPDX-License-Identifier: MIT
*/

/**
* Otherwise known as hexadecimal.
*/
export const customBase16Dict = "0123456789ABCDEF";

/**
* Base32 dictionary as defined in rfc4648:
* https://datatracker.ietf.org/doc/html/rfc4648#section-6
*/
export const customBase32Dict = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

/**
* Base64 dictionary using the more well-known extended hex format:
* https://datatracker.ietf.org/doc/html/rfc4648#section-7
*/
export const customBase32HexDict = "0123456789ABCDEEFGHIJKLMNOPQRSTU";

/**
* Base36 dictionary.
*/
export const customBase36Dict = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

/**
* Base58 dictionary.
*/
export const customBase58Dict = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

/**
* Base62 dictionary.
*/
export const customBase62Dict = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

/**
* Base64 dictionary:
* https://datatracker.ietf.org/doc/html/rfc4648#section-4
*/
export const customBase64Dict = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/**
* A simple dictionary for safe source-code inclusion. Effectively base91, as
* it contains base95 with all three quote types and the escape character
* removed.
*/
export const customSafeDict =
" !#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~";

/**
* Base95 dictionary.
* (Two escaped characters in source).
*/
export const customBase95Dict =
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

/**
* If the dictionary passed is a known named dictionary then return that,
* otherwise return the source and assume it's correct.
*/
export const getCustomDictionary = (dict: string) =>
({
safe: customSafeDict,
base16: customBase16Dict,
base32: customBase32Dict,
base32hex: customBase32HexDict,
base36: customBase36Dict,
base58: customBase58Dict,
base62: customBase62Dict,
base64: customBase64Dict,
base95: customBase95Dict,
}[dict]) || dict;
12 changes: 12 additions & 0 deletions src/custom/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,15 @@

export { compressToCustom } from "./compressToCustom";
export { decompressFromCustom } from "./decompressFromCustom";
export {
customSafeDict,
customBase16Dict,
customBase32Dict,
customBase32HexDict,
customBase36Dict,
customBase58Dict,
customBase62Dict,
customBase64Dict,
customBase95Dict,
getCustomDictionary,
} from "./dictionaries";
25 changes: 24 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,20 @@
import { _compress } from "./_compress";
import { _decompress } from "./_decompress";
import { compressToBase64, decompressFromBase64 } from "./base64";
import { compressToCustom, decompressFromCustom } from "./custom";
import {
compressToCustom,
customBase16Dict,
customBase32Dict,
customBase32HexDict,
customBase36Dict,
customBase58Dict,
customBase62Dict,
customBase64Dict,
customBase95Dict,
customSafeDict,
decompressFromCustom,
getCustomDictionary,
} from "./custom";
import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from "./encodedURIComponent";
import { loadBinaryFile, saveBinaryFile } from "./node";
import { compress, decompress } from "./raw";
Expand All @@ -30,12 +43,22 @@ export default {
compressToUTF16,
convertFromUint8Array,
convertToUint8Array,
customSafeDict,
customBase16Dict,
customBase32Dict,
customBase32HexDict,
customBase36Dict,
customBase58Dict,
customBase62Dict,
customBase64Dict,
customBase95Dict,
decompress,
decompressFromBase64,
decompressFromCustom,
decompressFromEncodedURIComponent,
decompressFromUint8Array,
decompressFromUTF16,
getCustomDictionary,
loadBinaryFile,
saveBinaryFile,
};
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"target": "ESNext",
"target": "ESNext"
},
"include": ["src"],
"include": ["src"]
}