blob: e9520e3a979fb42382772b297259e49712a0a072 [file] [log] [blame]
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Example of using package:wasm to run a wasm build of the Brotli compression
// library. Usage:
// dart brotli.dart input.txt
import 'dart:convert';
import "dart:io";
import "dart:typed_data";
import "package:wasm/wasm.dart";
// Brotli compression parameters.
const int kDefaultQuality = 11;
const int kDefaultWindow = 22;
const int kDefaultMode = 0;
main(List<String> args) {
var brotliPath = Platform.script.resolve('libbrotli.wasm');
var moduleData = File(brotliPath.path).readAsBytesSync();
var module = WasmModule(moduleData);
print(module.describe());
var instance = module.instantiate().enableWasi().build();
var memory = instance.memory;
var compress = instance.lookupFunction("BrotliEncoderCompress");
var decompress = instance.lookupFunction("BrotliDecoderDecompress");
print("Loading ${args[0]}");
var inputData = File(args[0]).readAsBytesSync();
print("Input size: ${inputData.length} bytes");
// Grow the module's memory to get unused space to put our data.
// [initial memory][input data][output data][size][decoded data][size]
var inputPtr = memory.lengthInBytes;
memory.grow((3 * inputData.length / WasmMemory.kPageSizeInBytes).ceil());
var memoryView = memory.view;
var outputPtr = inputPtr + inputData.length;
var outSizePtr = outputPtr + inputData.length;
var decodedPtr = outSizePtr + 4;
var decSizePtr = decodedPtr + inputData.length;
memoryView.setRange(inputPtr, inputPtr + inputData.length, inputData);
var sizeBytes = ByteData(4);
sizeBytes.setUint32(0, inputData.length, Endian.host);
memoryView.setRange(
outSizePtr, outSizePtr + 4, sizeBytes.buffer.asUint8List());
print("\nCompressing...");
var status = compress(kDefaultQuality, kDefaultWindow, kDefaultMode,
inputData.length, inputPtr, outSizePtr, outputPtr);
print("Compression status: $status");
var compressedSize =
ByteData.sublistView(memoryView, outSizePtr, outSizePtr + 4)
.getUint32(0, Endian.host);
print("Compressed size: $compressedSize bytes");
var spaceSaving = 100 * (1 - compressedSize / inputData.length);
print("Space saving: ${spaceSaving.toStringAsFixed(2)}%");
var decSizeBytes = ByteData(4);
decSizeBytes.setUint32(0, inputData.length, Endian.host);
memoryView.setRange(
decSizePtr, decSizePtr + 4, decSizeBytes.buffer.asUint8List());
print("\nDecompressing...");
status = decompress(compressedSize, outputPtr, decSizePtr, decodedPtr);
print("Decompression status: $status");
var decompressedSize =
ByteData.sublistView(memoryView, decSizePtr, decSizePtr + 4)
.getUint32(0, Endian.host);
print("Decompressed size: $decompressedSize bytes");
print("\nVerifying decompression...");
assert(inputData.length == decompressedSize);
for (var i = 0; i < inputData.length; ++i) {
assert(inputData[i] == memoryView[decodedPtr + i]);
}
print("Decompression succeeded :)");
}