├── .editorconfig ├── .github ├── FUNDING.yml └── workflows │ ├── deno.yml │ └── depsbot.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── bench.ts ├── deno.json ├── mod.ts ├── scripts └── build.ts ├── src └── lib.rs ├── test.ts ├── test_deps.ts └── wasm.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = space 7 | indent_size = 2 8 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | open_collective: denosaurs 2 | github: denosaurs 3 | -------------------------------------------------------------------------------- /.github/workflows/deno.yml: -------------------------------------------------------------------------------- 1 | name: deno 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | style: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: checkout repo 10 | uses: actions/checkout@v2 11 | 12 | - name: setup latest deno version 13 | uses: denoland/setup-deno@main 14 | with: 15 | deno-version: v1.x 16 | 17 | - name: run deno fmt 18 | run: deno fmt --check 19 | 20 | - name: run deno lint 21 | run: deno lint --unstable 22 | 23 | tests: 24 | name: ${{ matrix.kind }} ${{ matrix.os }} 25 | runs-on: ${{ matrix.os }} 26 | timeout-minutes: 10 27 | strategy: 28 | matrix: 29 | os: [macOS-latest, windows-latest, ubuntu-latest] 30 | steps: 31 | - name: Checkout sources 32 | uses: actions/checkout@v2 33 | 34 | - name: Setup latest deno version 35 | uses: denoland/setup-deno@main 36 | with: 37 | deno-version: v1.x 38 | 39 | - name: run deno test 40 | run: deno test -A --unstable 41 | -------------------------------------------------------------------------------- /.github/workflows/depsbot.yml: -------------------------------------------------------------------------------- 1 | name: depsbot 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | schedule: 9 | - cron: "0 0 */2 * *" 10 | 11 | jobs: 12 | run: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout Repository 16 | uses: actions/checkout@v2 17 | 18 | - name: Run depsbot 19 | uses: denosaurs/depsbot@master 20 | with: 21 | github_token: ${{ secrets.GITHUB_TOKEN }} 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ide 2 | .idea 3 | 4 | # cargo build 5 | target/ 6 | # wasm-pack 7 | pkg/ 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog], and this project adheres to 6 | [Semantic Versioning]. 7 | 8 | ## [0.1.5] - 2020-11-04 9 | 10 | ### Features 11 | 12 | - clean, fmt, lint scripts ([`0283878`]) 13 | - benchmarks ([`d20e382`]) 14 | 15 | ## [0.1.4] - 2020-07-14 16 | 17 | ### Bug Fixes 18 | 19 | - :construction_worker: Fix build name ([`4f64f21`]) 20 | 21 | ## [0.1.3] - 2020-06-01 22 | 23 | ### Bug Fixes 24 | 25 | - :fire: Removed wee_alloc to fix memory leak ([`4256de7`]) 26 | 27 | ## [0.1.2] - 2020-05-30 28 | 29 | ### Features 30 | 31 | - :zap: Add settings.json to improve vscode performance ([`a4a3cfb`]) 32 | 33 | ## [0.1.1] - 2020-05-28 34 | 35 | ### Features 36 | 37 | - add js minification to wasm.js ([`0410c54`]) 38 | 39 | ### Bug Fixes 40 | 41 | - add opt-level ([`53b18e5`]) 42 | 43 | ## [0.1.0] - 2020-05-28 44 | 45 | ### Bug Fixes 46 | 47 | - :art: deno fmt now ignores wasm.js ([`eade930`]) 48 | 49 | ## [0.0.1] - 2020-05-28 50 | 51 | ### Features 52 | 53 | - add Release and PR CIs ([`a4cc61c`]) 54 | - add examples for decompress ([`f670133`]) 55 | - add `decompress` to class ([`84a06bc`]) 56 | - bind `decompress` to plugin ([`fa5e90d`]) 57 | - add `decompress` to rust ([`891bb3d`]) 58 | - add `compress` method ([`9432503`]) 59 | - initial commit ([`cf3c6c2`]) 60 | 61 | ### Bug Fixes 62 | 63 | - decompress fails ([`9165eb1`]) 64 | 65 | [keep a changelog]: https://keepachangelog.com/en/1.0.0/ 66 | [semantic versioning]: https://semver.org/spec/v2.0.0.html 67 | [0.1.5]: https://github.com/denosaurs/deno_brotli/compare/0.1.4...0.1.5 68 | [`0283878`]: https://github.com/denosaurs/deno_brotli/commit/028387867a853ad1a7657b926a09535864400921 69 | [`d20e382`]: https://github.com/denosaurs/deno_brotli/commit/d20e382d7a2780b09887b5a91b51df98adb513ad 70 | [0.1.4]: https://github.com/denosaurs/deno_brotli/compare/0.1.3...0.1.4 71 | [`4f64f21`]: https://github.com/denosaurs/deno_brotli/commit/4f64f21a6b2405117c7f407d0bbbaa25ff9de632 72 | [0.1.3]: https://github.com/denosaurs/deno_brotli/compare/0.1.2...0.1.3 73 | [`4256de7`]: https://github.com/denosaurs/deno_brotli/commit/4256de731322bf5be710169af72cf11333972ff6 74 | [0.1.2]: https://github.com/denosaurs/deno_brotli/compare/0.1.1...0.1.2 75 | [`a4a3cfb`]: https://github.com/denosaurs/deno_brotli/commit/a4a3cfbc2d7edc62ac7fea901e9b4b197d4ab593 76 | [0.1.1]: https://github.com/denosaurs/deno_brotli/compare/0.1.0...0.1.1 77 | [`0410c54`]: https://github.com/denosaurs/deno_brotli/commit/0410c548125f7e793ae0fdaeca4ce4d0cc60928e 78 | [`53b18e5`]: https://github.com/denosaurs/deno_brotli/commit/53b18e5e3994aaebc017403e686a6a7a1249c69a 79 | [0.1.0]: https://github.com/denosaurs/deno_brotli/compare/0.0.1...0.1.0 80 | [`eade930`]: https://github.com/denosaurs/deno_brotli/commit/eade930b76e317d190903e4dbd56bb71e87ffbb8 81 | [0.0.1]: https://github.com/denosaurs/deno_brotli/compare/0.0.1 82 | [`a4cc61c`]: https://github.com/denosaurs/deno_brotli/commit/a4cc61c862dadcd0aae80a02942a320036ea3285 83 | [`f670133`]: https://github.com/denosaurs/deno_brotli/commit/f6701338a4c8b9a4c0f0b93b45d5f6f7cac67e64 84 | [`84a06bc`]: https://github.com/denosaurs/deno_brotli/commit/84a06bcb1eb249de66b1dd9e58fdfc52986780d9 85 | [`fa5e90d`]: https://github.com/denosaurs/deno_brotli/commit/fa5e90d6c990f9be46b3c615a5faf77952620954 86 | [`891bb3d`]: https://github.com/denosaurs/deno_brotli/commit/891bb3d3746e235406b06743f86cfda454506c87 87 | [`9432503`]: https://github.com/denosaurs/deno_brotli/commit/94325038308388807b9d08831fb3830d9bf1b3ff 88 | [`cf3c6c2`]: https://github.com/denosaurs/deno_brotli/commit/cf3c6c2e929a286a510b091c8cab494e79643f0b 89 | [`9165eb1`]: https://github.com/denosaurs/deno_brotli/commit/9165eb1539999a1b5707559d6e6eee0d6ff7f7f9 90 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "alloc-no-stdlib" 7 | version = "2.0.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "5192ec435945d87bc2f70992b4d818154b5feede43c09fb7592146374eac90a6" 10 | 11 | [[package]] 12 | name = "alloc-stdlib" 13 | version = "0.2.1" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2" 16 | dependencies = [ 17 | "alloc-no-stdlib", 18 | ] 19 | 20 | [[package]] 21 | name = "brotli" 22 | version = "3.3.4" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" 25 | dependencies = [ 26 | "alloc-no-stdlib", 27 | "alloc-stdlib", 28 | "brotli-decompressor", 29 | ] 30 | 31 | [[package]] 32 | name = "brotli-decompressor" 33 | version = "2.3.1" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "1052e1c3b8d4d80eb84a8b94f0a1498797b5fb96314c001156a1c761940ef4ec" 36 | dependencies = [ 37 | "alloc-no-stdlib", 38 | "alloc-stdlib", 39 | ] 40 | 41 | [[package]] 42 | name = "bumpalo" 43 | version = "3.4.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" 46 | 47 | [[package]] 48 | name = "cfg-if" 49 | version = "0.1.10" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 52 | 53 | [[package]] 54 | name = "cfg-if" 55 | version = "1.0.0" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 58 | 59 | [[package]] 60 | name = "deno_brotli" 61 | version = "0.1.5" 62 | dependencies = [ 63 | "brotli", 64 | "wasm-bindgen", 65 | ] 66 | 67 | [[package]] 68 | name = "log" 69 | version = "0.4.8" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 72 | dependencies = [ 73 | "cfg-if 0.1.10", 74 | ] 75 | 76 | [[package]] 77 | name = "once_cell" 78 | version = "1.15.0" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" 81 | 82 | [[package]] 83 | name = "proc-macro2" 84 | version = "1.0.46" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" 87 | dependencies = [ 88 | "unicode-ident", 89 | ] 90 | 91 | [[package]] 92 | name = "quote" 93 | version = "1.0.7" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" 96 | dependencies = [ 97 | "proc-macro2", 98 | ] 99 | 100 | [[package]] 101 | name = "syn" 102 | version = "1.0.102" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" 105 | dependencies = [ 106 | "proc-macro2", 107 | "quote", 108 | "unicode-ident", 109 | ] 110 | 111 | [[package]] 112 | name = "unicode-ident" 113 | version = "1.0.5" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" 116 | 117 | [[package]] 118 | name = "wasm-bindgen" 119 | version = "0.2.83" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" 122 | dependencies = [ 123 | "cfg-if 1.0.0", 124 | "wasm-bindgen-macro", 125 | ] 126 | 127 | [[package]] 128 | name = "wasm-bindgen-backend" 129 | version = "0.2.83" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" 132 | dependencies = [ 133 | "bumpalo", 134 | "log", 135 | "once_cell", 136 | "proc-macro2", 137 | "quote", 138 | "syn", 139 | "wasm-bindgen-shared", 140 | ] 141 | 142 | [[package]] 143 | name = "wasm-bindgen-macro" 144 | version = "0.2.83" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" 147 | dependencies = [ 148 | "quote", 149 | "wasm-bindgen-macro-support", 150 | ] 151 | 152 | [[package]] 153 | name = "wasm-bindgen-macro-support" 154 | version = "0.2.83" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" 157 | dependencies = [ 158 | "proc-macro2", 159 | "quote", 160 | "syn", 161 | "wasm-bindgen-backend", 162 | "wasm-bindgen-shared", 163 | ] 164 | 165 | [[package]] 166 | name = "wasm-bindgen-shared" 167 | version = "0.2.83" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" 170 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "deno_brotli" 3 | description = "Brotli wasm module for deno" 4 | repository = "https://github.com/denosaurs/deno_brotli" 5 | license = "MIT" 6 | version = "0.1.5" 7 | authors = ["Elias Sjögreen", "Divy Srivastava", "Filippo Rossi"] 8 | edition = "2021" 9 | publish = false 10 | 11 | [lib] 12 | crate-type = ["cdylib"] 13 | 14 | [dependencies] 15 | wasm-bindgen = "0.2.83" 16 | brotli = "3.3.4" 17 | 18 | [profile.release] 19 | codegen-units = 1 20 | opt-level = 3 21 | lto = true 22 | 23 | [profile.release.package."*"] 24 | opt-level = 3 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2022 the denosaurs team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # deno_brotli 2 | 3 | [![stars](https://img.shields.io/github/stars/denosaurs/deno_brotli)](https://github.com/denosaurs/deno_brotli/stargazers) 4 | [![workflow](https://img.shields.io/github/workflow/status/denosaurs/deno_brotli/ci)](https://github.com/denosaurs/deno_brotli/actions) 5 | [![releases](https://img.shields.io/github/v/release/denosaurs/deno_brotli)](https://github.com/denosaurs/deno_brotli/releases/latest/) 6 | [![deno version](https://img.shields.io/badge/deno-^1.0.2-informational)](https://github.com/denoland/deno) 7 | [![deno doc](https://img.shields.io/badge/deno-doc-informational)](https://doc.deno.land/https/deno.land/x/deno_brotli/mod.ts) 8 | [![Discord](https://img.shields.io/discord/713043818806509608)](https://discord.gg/shHG8vg) 9 | [![license](https://img.shields.io/github/license/denosaurs/deno_brotli)](https://github.com/denosaurs/deno_brotli/blob/master/LICENSE) 10 | [![issues](https://img.shields.io/github/issues/denosaurs/deno_brotli)](https://github.com/denosaurs/deno_brotli/issues) 11 | 12 | This module provides [brotli](https://en.wikipedia.org/wiki/Brotli) support for 13 | deno and the web by providing [simple bindings](src/lib.rs) using 14 | [rust-brotli](https://github.com/dropbox/rust-brotli) compiled to webassembly. 15 | 16 | ## Usage 17 | 18 | ### Compression 19 | 20 | ```ts 21 | import { compress } from "https://deno.land/x/brotli/mod.ts"; 22 | 23 | const text = new TextEncoder().encode("X".repeat(64)); 24 | 25 | console.log(text.length); // 64 Bytes 26 | console.log(compress(text).length); // 10 Bytes 27 | ``` 28 | 29 | ### Decompression 30 | 31 | ```ts 32 | import { decompress } from "https://deno.land/x/brotli/mod.ts"; 33 | 34 | const compressed = Uint8Array.from([27, 63, 0, 0, 36, 176, 226, 153, 64, 18]); 35 | 36 | console.log(compressed.length); // 10 Bytes 37 | console.log(decompress(compressed).length); // 64 Bytes 38 | ``` 39 | 40 | ## Other 41 | 42 | ### Contribution 43 | 44 | Pull request, issues and feedback are very welcome. Code style is formatted with 45 | `deno fmt` and commit messages are done following 46 | [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) spec. 47 | 48 | ### Licence 49 | 50 | Copyright 2020-2022, the denosaurs team. All rights reserved. MIT license. 51 | -------------------------------------------------------------------------------- /bench.ts: -------------------------------------------------------------------------------- 1 | import { compress, decompress } from "./mod.ts"; 2 | 3 | { 4 | const original = new Uint8Array(65536); 5 | crypto.getRandomValues(original); 6 | 7 | Deno.bench({ 8 | name: "compress", 9 | fn: () => { 10 | compress(original); 11 | }, 12 | }); 13 | } 14 | 15 | { 16 | const original = new Uint8Array(65536); 17 | crypto.getRandomValues(original); 18 | const compressed = compress(original); 19 | 20 | Deno.bench({ 21 | name: "decompress", 22 | fn: () => { 23 | decompress(compressed); 24 | }, 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "build": "deno run -A --unstable ./scripts/build.ts" 4 | }, 5 | "fmt": { 6 | "files": { 7 | "exclude": [ 8 | "wasm.js", 9 | "pkg/", 10 | "target/" 11 | ] 12 | } 13 | }, 14 | "lint": { 15 | "files": { 16 | "exclude": [ 17 | "wasm.js", 18 | "pkg/", 19 | "target/" 20 | ] 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /mod.ts: -------------------------------------------------------------------------------- 1 | import init, { 2 | compress as wasmCompress, 3 | decompress as wasmDecompress, 4 | source, 5 | } from "./wasm.js"; 6 | 7 | await init(source); 8 | 9 | /** 10 | * Compress a byte array. 11 | * 12 | * ```typescript 13 | * import { compress } from "https://deno.land/x/brotli/mod.ts"; 14 | * const text = new TextEncoder().encode("X".repeat(64)); 15 | * console.log(text.length); // 64 Bytes 16 | * console.log(compress(text).length); // 10 Bytes 17 | * ``` 18 | * 19 | * @param input Input data. 20 | * @param bufferSize Read buffer size 21 | * @param quality Controls the compression-speed vs compression- 22 | * density tradeoff. The higher the quality, the slower the compression. 23 | * @param lgwin Base 2 logarithm of the sliding window size. 24 | */ 25 | export function compress( 26 | input: Uint8Array, 27 | bufferSize = 4096, 28 | quality = 6, 29 | lgwin = 22, 30 | ): Uint8Array { 31 | return wasmCompress(input, bufferSize, quality, lgwin); 32 | } 33 | 34 | /** 35 | * Decompress a byte array. 36 | * 37 | * ```typescript 38 | * import { decompress } from "https://deno.land/x/brotli/mod.ts"; 39 | * const compressed = Uint8Array.from([ 27, 63, 0, 0, 36, 176, 226, 153, 64, 18 ]); 40 | * console.log(compressed.length); // 10 Bytes 41 | * console.log(decompress(compressed).length); // 64 Bytes 42 | * ``` 43 | * 44 | * @param input Input data. 45 | * @param bufferSize Read buffer size 46 | */ 47 | export function decompress( 48 | input: Uint8Array, 49 | bufferSize = 4096, 50 | ): Uint8Array { 51 | return wasmDecompress(input, bufferSize); 52 | } 53 | -------------------------------------------------------------------------------- /scripts/build.ts: -------------------------------------------------------------------------------- 1 | import { encode } from "https://deno.land/std@0.159.0/encoding/ascii85.ts"; 2 | import { compress } from "https://deno.land/x/lz4@v0.1.2/mod.ts"; 3 | import { minify } from "https://esm.sh/terser@5.15.1"; 4 | 5 | const name = "deno_brotli"; 6 | const target = "wasm.js"; 7 | const encoder = new TextEncoder(); 8 | 9 | export async function build() { 10 | if (!(await Deno.stat("Cargo.toml")).isFile) { 11 | console.log(`the build script should be executed in the "${name}" root`); 12 | Deno.exit(1); 13 | } 14 | 15 | console.log("building rust"); 16 | await Deno.run({ 17 | cmd: ["wasm-pack", "build", "--target", "web", "--release"], 18 | }).status(); 19 | 20 | const wasm = await Deno.readFile(`pkg/${name}_bg.wasm`); 21 | console.log(`read wasm (size: ${wasm.length} bytes)`); 22 | const compressed = compress(wasm); 23 | console.log( 24 | `compressed wasm using lz4 (reduction: ${ 25 | wasm.length - 26 | compressed.length 27 | } bytes, size: ${compressed.length})`, 28 | ); 29 | const encoded = encode(compressed) 30 | .replaceAll("\\", "\\\\") 31 | .replaceAll("`", "\\`"); 32 | console.log( 33 | `encoded wasm using base64, (increase: ${ 34 | encoded.length - 35 | compressed.length 36 | } bytes, size: ${encoded.length})`, 37 | ); 38 | 39 | console.log("inlining wasm and init code in js"); 40 | const init = await Deno.readTextFile(`pkg/${name}.js`); 41 | const source = `import * as lz4 from "https://deno.land/x/lz4@v0.1.2/mod.ts"; 42 | import { decode } from "https://deno.land/std@0.159.0/encoding/ascii85.ts"; 43 | export const source = lz4.decompress(decode(\`${encoded}\`)); 44 | ${init}`; 45 | 46 | console.log("minifying js using terser"); 47 | const output = await minify(source, { 48 | mangle: { module: true }, 49 | output: { 50 | preamble: `// deno-lint-ignore-file\n// deno-fmt-ignore-file`, 51 | }, 52 | }); 53 | 54 | const reduction = new Blob([source]).size - 55 | new Blob([output.code!]).size; 56 | console.log(`minified js, size reduction: ${reduction} bytes`); 57 | 58 | console.log(`writing output to file (${target})`); 59 | await Deno.writeFile(target, encoder.encode(output.code)); 60 | 61 | const outputFile = await Deno.stat(target); 62 | console.log( 63 | `output file (${target}), final size is: ${outputFile.size} bytes`, 64 | ); 65 | } 66 | 67 | if (import.meta.main) { 68 | await build(); 69 | } 70 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use brotli::{CompressorWriter, DecompressorWriter}; 2 | use std::io::Write; 3 | use wasm_bindgen::prelude::wasm_bindgen; 4 | 5 | #[wasm_bindgen] 6 | pub fn compress(input: &[u8], buffer_size: usize, quality: u32, lgwin: u32) -> Vec { 7 | let mut output = Vec::new(); 8 | { 9 | let mut writer = CompressorWriter::new(&mut output, buffer_size, quality, lgwin); 10 | writer.write_all(input).unwrap(); 11 | } 12 | output 13 | } 14 | 15 | #[wasm_bindgen] 16 | pub fn decompress(input: &[u8], buffer_size: usize) -> Vec { 17 | let mut output = Vec::new(); 18 | { 19 | let mut writer = DecompressorWriter::new(&mut output, buffer_size); 20 | writer.write_all(input).unwrap(); 21 | } 22 | output 23 | } 24 | 25 | #[test] 26 | pub fn compress_test() { 27 | const BUFFER_SIZE: usize = 4692; 28 | const QUALITY: u32 = 6; 29 | const WINDOW_SIZE: u32 = 22; 30 | assert_eq!( 31 | compress("".as_bytes(), BUFFER_SIZE, QUALITY, WINDOW_SIZE), 32 | [59] 33 | ); 34 | assert_eq!( 35 | compress("X".repeat(64).as_bytes(), BUFFER_SIZE, QUALITY, WINDOW_SIZE), 36 | [27, 63, 0, 0, 36, 176, 226, 153, 64, 18] 37 | ) 38 | } 39 | 40 | #[test] 41 | pub fn decompress_test() { 42 | const BUFFER_SIZE: usize = 4692; 43 | assert_eq!(decompress(&[59], BUFFER_SIZE), "".as_bytes()); 44 | assert_eq!( 45 | decompress(&[27, 63, 0, 0, 36, 176, 226, 153, 64, 18], BUFFER_SIZE), 46 | "X".repeat(64).as_bytes() 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /test.ts: -------------------------------------------------------------------------------- 1 | import { assertEquals } from "https://deno.land/std@0.159.0/testing/asserts.ts"; 2 | import { compress, decompress } from "./mod.ts"; 3 | 4 | function encode(input: string): Uint8Array { 5 | return new TextEncoder().encode(input); 6 | } 7 | 8 | Deno.test({ 9 | name: "compress", 10 | fn: () => { 11 | // empty 12 | assertEquals(compress(encode("")), new Uint8Array([59])); 13 | // 'X' x64 times 14 | assertEquals( 15 | compress(encode("X".repeat(64))), 16 | new Uint8Array([27, 63, 0, 0, 36, 176, 226, 153, 64, 18]), 17 | ); 18 | }, 19 | }); 20 | 21 | Deno.test({ 22 | name: "decompress", 23 | fn: () => { 24 | // empty 25 | assertEquals(decompress(Uint8Array.from([59])), new Uint8Array([])); 26 | // 'X' x64 times 27 | assertEquals( 28 | decompress(Uint8Array.from([27, 63, 0, 0, 36, 176, 226, 153, 64, 18])), 29 | encode("X".repeat(64)), 30 | ); 31 | }, 32 | }); 33 | -------------------------------------------------------------------------------- /test_deps.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/denosaurs/deno_brotli/edab99650ae497d70407a3939a8182378f3b02eb/test_deps.ts --------------------------------------------------------------------------------