blob: f91e4343181436901cff4110aa3364bb94d6ba35 [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: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;
void 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)..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)..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 :)');
}