1
0
Fork 0
mirror of https://github.com/codedread/bitjs synced 2025-10-03 17:49:16 +02:00

Some minor API updates.

This commit is contained in:
Jeff Schiller 2021-12-29 20:01:48 -08:00
parent 24b1603968
commit cc59935e72
7 changed files with 139 additions and 10 deletions

View file

@ -2,6 +2,7 @@
* archive.js * archive.js
* *
* Provides base functionality for unarchiving. * Provides base functionality for unarchiving.
* DEPRECATED: Use decompress.js instead.
* *
* Licensed under the MIT License * Licensed under the MIT License
* *
@ -12,7 +13,9 @@ import { UnarchiveAppendEvent, UnarchiveErrorEvent, UnarchiveEvent, UnarchiveEve
UnarchiveExtractEvent, UnarchiveFinishEvent, UnarchiveInfoEvent, UnarchiveExtractEvent, UnarchiveFinishEvent, UnarchiveInfoEvent,
UnarchiveProgressEvent, UnarchiveStartEvent, Unarchiver, UnarchiveProgressEvent, UnarchiveStartEvent, Unarchiver,
UnrarrerInternal, UntarrerInternal, UnzipperInternal, UnrarrerInternal, UntarrerInternal, UnzipperInternal,
getUnarchiverInternal } from './archive-internal.js'; getUnarchiverInternal } from './decompress-internal.js';
console.warn(`Stop using archive.js and use decompress.js instead. This module will be removed.`);
export { export {
UnarchiveAppendEvent, UnarchiveAppendEvent,

View file

@ -1,6 +1,4 @@
import { ByteBuffer } from '../io/bytebuffer.js';
// NOTE: THIS IS A VERY HACKY WORK-IN-PROGRESS! THE API IS NOT FROZEN! USE AT YOUR OWN RISK! // NOTE: THIS IS A VERY HACKY WORK-IN-PROGRESS! THE API IS NOT FROZEN! USE AT YOUR OWN RISK!
/** /**
@ -10,9 +8,35 @@ import { ByteBuffer } from '../io/bytebuffer.js';
* @property {ArrayBuffer} fileData The bytes of the file. * @property {ArrayBuffer} fileData The bytes of the file.
*/ */
/**
* @readonly
* @enum {number}
*/
export const ZipCompressionMethod = {
STORE: 0, // Default.
// DEFLATE: 8,
};
// export const DeflateCompressionMethod = {
// NO_COMPRESSION: 0,
// COMPRESSION_FIXED_HUFFMAN: 1,
// COMPRESSION_DYNAMIC_HUFFMAN: 2,
// }
/**
* Data elements are packed into bytes in order of increasing bit number within the byte,
i.e., starting with the least-significant bit of the byte.
* Data elements other than Huffman codes are packed starting with the least-significant bit of the
data element.
* Huffman codes are packed starting with the most-significant bit of the code.
*/
/** /**
* @typedef CompressorOptions * @typedef CompressorOptions
* @property {string} pathToBitJS A string indicating where the BitJS files are located. * @property {string} pathToBitJS A string indicating where the BitJS files are located.
* @property {ZipCompressionMethod} zipCompressionMethod
* @property {DeflateCompressionMethod=} deflateCompressionMethod Only present if
* zipCompressionMethod is set to DEFLATE.
*/ */
/** /**
@ -30,6 +54,7 @@ export const CompressStatus = {
/** /**
* A thing that zips files. * A thing that zips files.
* NOTE: THIS IS A VERY HACKY WORK-IN-PROGRESS! THE API IS NOT FROZEN! USE AT YOUR OWN RISK! * NOTE: THIS IS A VERY HACKY WORK-IN-PROGRESS! THE API IS NOT FROZEN! USE AT YOUR OWN RISK!
* TODO: Make a streaming / event-driven API.
*/ */
export class Zipper { export class Zipper {
/** /**
@ -43,6 +68,12 @@ export class Zipper {
*/ */
this.pathToBitJS = options.pathToBitJS || '/'; this.pathToBitJS = options.pathToBitJS || '/';
/**
* @type {ZipCompressionMethod}
* @private
*/
this.zipCompressionMethod = options.zipCompressionMethod || ZipCompressionMethod.STORE;
/** /**
* Private web worker initialized during start(). * Private web worker initialized during start().
* @type {Worker} * @type {Worker}
@ -80,9 +111,13 @@ export class Zipper {
} }
/** /**
* Send in a set of files to be compressed. Set isLastFile to true if no more files are to added
* at some future state. The Promise will not resolve until isLastFile is set to true either in
* this method or in appendFiles().
* @param {FileInfo[]} files * @param {FileInfo[]} files
* @param {boolean} isLastFile * @param {boolean} isLastFile
* @returns {Promise<Uint8Array>} A Promise that contains the entire zipped archive. * @returns {Promise<Uint8Array>} A Promise that will contain the entire zipped archive as an array
* of bytes.
*/ */
start(files, isLastFile) { start(files, isLastFile) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View file

@ -207,11 +207,15 @@ export class UnarchiveExtractEvent extends UnarchiveEvent {
*/ */
this.pathToBitJS_ = options.pathToBitJS || '/'; this.pathToBitJS_ = options.pathToBitJS || '/';
/** @orivate {boolean} */ /**
* @orivate
* @type {boolean}
*/
this.debugMode_ = !!(options.debug); this.debugMode_ = !!(options.debug);
/** /**
* A map from event type to an array of listeners. * A map from event type to an array of listeners.
* @private
* @type {Map.<string, Array>} * @type {Map.<string, Array>}
*/ */
this.listeners_ = {}; this.listeners_ = {};
@ -221,8 +225,8 @@ export class UnarchiveExtractEvent extends UnarchiveEvent {
/** /**
* Private web worker initialized during start(). * Private web worker initialized during start().
* @type {Worker}
* @private * @private
* @type {Worker}
*/ */
this.worker_ = null; this.worker_ = null;
} }

84
archive/decompress.js Normal file
View file

@ -0,0 +1,84 @@
/**
* decompress.js
*
* Provides base functionality for unarchiving/decompression.
*
* Licensed under the MIT License
*
* Copyright(c) 2021 Google Inc.
*/
import { UnarchiveAppendEvent, UnarchiveErrorEvent, UnarchiveEvent, UnarchiveEventType,
UnarchiveExtractEvent, UnarchiveFinishEvent, UnarchiveInfoEvent,
UnarchiveProgressEvent, UnarchiveStartEvent, Unarchiver,
UnrarrerInternal, UntarrerInternal, UnzipperInternal,
getUnarchiverInternal } from './decompress-internal.js';
export {
UnarchiveAppendEvent,
UnarchiveErrorEvent,
UnarchiveEvent,
UnarchiveEventType,
UnarchiveExtractEvent,
UnarchiveFinishEvent,
UnarchiveInfoEvent,
UnarchiveProgressEvent,
UnarchiveStartEvent,
Unarchiver,
}
/**
* All extracted files returned by an Unarchiver will implement
* the following interface:
*/
/**
* @typedef UnarchivedFile
* @property {string} filename
* @property {Uint8Array} fileData
*/
/**
* The goal is to make this testable - send getUnarchiver() an array buffer of
* an archive, call start on the unarchiver, expect the returned result.
*
* Problem: It relies on Web Workers, and that won't work in a nodejs context.
* Solution: Make archive.js very thin, have it feed web-specific things into
* an internal module that is isomorphic JavaScript.
*
* TODO:
* - write unit tests for archive-internal.js that use the nodejs Worker
* equivalent.
* - maybe use @pgriess/node-webworker or @audreyt/node-webworker-threads or
* just node's worker_threads ?
*/
const createWorkerFn = (scriptFilename) => new Worker(scriptFilename);
// Thin wrappers of compressors for clients who want to construct a specific
// unarchiver themselves rather than use getUnarchiver().
export class Unzipper extends UnzipperInternal {
constructor(ab, options) { super(ab, createWorkerFn, options); }
}
export class Unrarrer extends UnrarrerInternal {
constructor(ab, options) { super(ab, createWorkerFn, options); }
}
export class Untarrer extends UntarrerInternal {
constructor(ab, options) { super(ab, createWorkerFn, options); }
}
/**
* Factory method that creates an unarchiver based on the byte signature found
* in the arrayBuffer.
* @param {ArrayBuffer} ab The ArrayBuffer to unarchive. Note that this ArrayBuffer
* must not be referenced after calling this method, as the ArrayBuffer is marked
* as Transferable and sent to a Worker thread once start() is called.
* @param {Object|string} options An optional object of options, or a string
* representing where the path to the unarchiver script files.
* @return {Unarchiver}
*/
export function getUnarchiver(ab, options = {}) {
return getUnarchiverInternal(ab, createWorkerFn, options);
}

View file

@ -493,7 +493,7 @@ function inflate(compressedData, numDecompressedBytes) {
// Bit stream representing the compressed data. // Bit stream representing the compressed data.
/** @type {bitjs.io.BitStream} */ /** @type {bitjs.io.BitStream} */
const bstream = new bitjs.io.BitStream(compressedData.buffer, const bstream = new bitjs.io.BitStream(compressedData.buffer,
false /* rtl */, false /* mtl */,
compressedData.byteOffset, compressedData.byteOffset,
compressedData.byteLength); compressedData.byteLength);
/** @type {bitjs.io.ByteBuffer} */ /** @type {bitjs.io.ByteBuffer} */

View file

@ -2,4 +2,4 @@
1. Create a zip or rar file with just one file inside it. 1. Create a zip or rar file with just one file inside it.
2. Use test-uploader.html and choose the archived file and the unarchived file. 2. Use test-uploader.html and choose the archived file and the unarchived file.
3. Paste that jSON output into a test json file. 3. Paste that JSON output into a test json file.

View file

@ -1,5 +1,5 @@
import { Zipper } from '../archive/compress.js'; import { Zipper, ZipCompressionMethod } from '../archive/compress.js';
const result = document.querySelector('#result'); const result = document.querySelector('#result');
const fileInputEl = document.querySelector('#zip-tester'); const fileInputEl = document.querySelector('#zip-tester');
@ -36,7 +36,10 @@ async function getFiles(fileChangeEvt) {
result.innerHTML = `Loaded files`; result.innerHTML = `Loaded files`;
const zipper = new Zipper({ pathToBitJS: '../' }); const zipper = new Zipper({
pathToBitJS: '../',
zipCompressionMethod: ZipCompressionMethod.DEFLATE,
});
byteArray = await zipper.start(fileInfos, true); byteArray = await zipper.start(fileInfos, true);
result.innerHTML = `Zipping done`; result.innerHTML = `Zipping done`;
saveButtonEl.style.display = ''; saveButtonEl.style.display = '';