@awayjs/graphics
Version:
AwayJS graphics classes
912 lines (818 loc) • 24.9 kB
text/typescript
/**
* Copyright 2014 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//import notImplemented = Shumway.Debug.notImplemented;
import { assert, IDataDecoder, isNullOrUndefined, ArrayBufferPool, clamp, Errors, IntegerUtilities, utf8decode, utf8encode } from './utilities';
import { Deflate, Inflate } from './deflate';
import { LzmaDecoder } from './lzma';
function axCoerceString(x): string {
if (typeof x === 'string') {
return x;
} else if (x == undefined) {
return null;
}
return x + '';
}
export interface IDataInput {
readBytes: (bytes: DataBuffer, offset?: number /*uint*/, length?: number /*uint*/) => void;
readBoolean: () => boolean;
readByte: () => number /*int*/;
readUnsignedByte: () => number /*uint*/;
readShort: () => number /*int*/;
readUnsignedShort: () => number /*uint*/;
readInt: () => number /*int*/;
readUnsignedInt: () => number /*uint*/;
readFloat: () => number;
readDouble: () => number;
readMultiByte: (length: number /*uint*/, charSet: string) => string;
readUTF: () => string;
readUTFBytes: (length: number /*uint*/) => string;
bytesAvailable: number /*uint*/;
objectEncoding: number /*uint*/;
endian: string;
}
export interface IDataOutput {
writeBytes: (bytes: DataBuffer, offset?: number /*uint*/, length?: number /*uint*/) => void;
writeBoolean: (value: boolean) => void;
writeByte: (value: number /*int*/) => void;
writeShort: (value: number /*int*/) => void;
writeInt: (value: number /*int*/) => void;
writeUnsignedInt: (value: number /*uint*/) => void;
writeFloat: (value: number) => void;
writeDouble: (value: number) => void;
writeMultiByte: (value: string, charSet: string) => void;
writeUTF: (value: string) => void;
writeUTFBytes: (value: string) => void;
objectEncoding: number /*uint*/;
endian: string;
}
export class PlainObjectDataBuffer {
constructor(public buffer: ArrayBuffer, public length: number, public littleEndian: boolean) {
}
}
const bitMasks = new Uint32Array(33);
for (let i = 1, mask = 0; i <= 32; i++) {
bitMasks[i] = mask = (mask << 1) | 1;
}
enum TypedArrayViewFlags {
U8 = 1,
I32 = 2,
F32 = 4
}
export class DataBuffer implements IDataInput, IDataOutput {
private static _nativeLittleEndian = new Int8Array(new Int32Array([1]).buffer)[0] === 1;
/* The initial size of the backing, in bytes. Doubled every OOM. */
private static INITIAL_SIZE = 128;
private _buffer: ArrayBuffer;
private _length: number;
private _position: number;
private _littleEndian: boolean;
private _objectEncoding: number;
private _u8: Uint8Array;
private _i32: Int32Array;
private _f32: Float32Array;
private _bitBuffer: number;
private _bitLength: number;
private static _arrayBufferPool = new ArrayBufferPool();
constructor(initialSize: number = DataBuffer.INITIAL_SIZE) {
// If we're constructing a child class of DataBuffer (or ByteArray), buffer initialization
// has already happened at this point.
if (this._buffer) {
return;
}
this._buffer = new ArrayBuffer(initialSize);
this._length = 0;
this._position = 0;
this._resetViews();
this._littleEndian = DataBuffer._nativeLittleEndian;
this._bitBuffer = 0;
this._bitLength = 0;
}
static FromArrayBuffer(buffer: ArrayBuffer, length: number = -1): DataBuffer {
const dataBuffer: DataBuffer = Object.create(DataBuffer.prototype);
dataBuffer._buffer = buffer;
dataBuffer._length = length === -1 ? buffer.byteLength : length;
dataBuffer._position = 0;
dataBuffer._resetViews();
dataBuffer._littleEndian = DataBuffer._nativeLittleEndian;
dataBuffer._bitBuffer = 0;
dataBuffer._bitLength = 0;
return dataBuffer;
}
static FromPlainObject(source: PlainObjectDataBuffer): DataBuffer {
const dataBuffer = DataBuffer.FromArrayBuffer(source.buffer, source.length);
dataBuffer._littleEndian = source.littleEndian;
return dataBuffer;
}
toPlainObject(): PlainObjectDataBuffer {
return new PlainObjectDataBuffer(this._buffer, this._length, this._littleEndian);
}
/**
* Clone the DataBuffer in a way that guarantees the underlying ArrayBuffer to be copied
* into an instance of the current global's ArrayBuffer.
*
* Important if the underlying buffer comes from a different global, in which case accessing
* its elements is excruiciatingly slow.
*/
clone(): DataBuffer {
const clone = DataBuffer.FromArrayBuffer(new Uint8Array(this._u8).buffer, this._length);
clone._position = this._position;
clone._littleEndian = this._littleEndian;
clone._bitBuffer = this._bitBuffer;
clone._bitLength = this._bitLength;
return clone;
}
/**
* By default, we only have a byte view. All other views are |null|.
*/
private _resetViews() {
this._u8 = new Uint8Array(this._buffer);
this._i32 = null;
this._f32 = null;
}
/**
* We don't want to eagerly allocate views if we won't ever need them. You must call this method
* before using a view of a certain type to make sure it's available. Once a view is allocated,
* it is not re-allocated unless the view becomes |null| as a result of a call to |resetViews|.
*/
private _requestViews(flags: TypedArrayViewFlags) {
if ((this._buffer.byteLength & 0x3) === 0) {
if (this._i32 === null && flags & TypedArrayViewFlags.I32) {
this._i32 = new Int32Array(this._buffer);
}
if (this._f32 === null && flags & TypedArrayViewFlags.F32) {
this._f32 = new Float32Array(this._buffer);
}
}
}
getBytes(): Uint8Array {
return new Uint8Array(this._buffer, 0, this._length);
}
private _ensureCapacity(length: number) {
const currentBuffer = this._buffer;
if (currentBuffer.byteLength >= length) {
return;
}
let newLength = Math.max(currentBuffer.byteLength, 1);
while (newLength < length) {
newLength *= 2;
}
if (newLength > 0xFFFFFFFF) {
assert((<any> this).sec);
(<any> this).sec.throwError('RangeError', Errors.ParamRangeError);
}
const newBuffer = DataBuffer._arrayBufferPool.acquire(newLength);
const curentView = this._u8;
this._buffer = newBuffer;
this._resetViews();
this._u8.set(curentView);
const u8 = this._u8;
// Zero out the rest of the buffer, since the arrayBufferPool doesn't
// always give us a empty buffer.
for (let i = curentView.length; i < u8.length; i++) {
u8[i] = 0;
}
DataBuffer._arrayBufferPool.release(currentBuffer);
}
clear() {
this._length = 0;
this._position = 0;
}
readBoolean(): boolean {
return this.readUnsignedByte() !== 0;
}
readByte(): number /*int*/ {
return this.readUnsignedByte() << 24 >> 24;
}
readUnsignedByte(): number /*uint*/ {
if (this._position + 1 > this._length) {
assert((<any> this).sec);
(<any> this).sec.throwError('flash.errors.EOFError', Errors.EOFError);
}
return this._u8[this._position++];
}
readBytes(bytes: DataBuffer, offset?: number /*uint*/, length?: number /*uint*/): void {
const position = this._position;
offset = offset >>> 0;
length = length >>> 0;
if (length === 0) {
length = this._length - position;
}
if (position + length > this._length) {
assert((<any> this).sec);
(<any> this).sec.throwError('flash.errors.EOFError', Errors.EOFError);
}
if (bytes.length < offset + length) {
bytes._ensureCapacity(offset + length);
bytes.length = offset + length;
}
bytes._u8.set(new Uint8Array(this._buffer, position, length), offset);
this._position += length;
}
readShort(): number /*int*/ {
return this.readUnsignedShort() << 16 >> 16;
}
readUnsignedShort(): number /*uint*/ {
const u8 = this._u8;
const position = this._position;
if (position + 2 > this._length) {
assert((<any> this).sec);
(<any> this).sec.throwError('flash.errors.EOFError', Errors.EOFError);
}
const a = u8[position + 0];
const b = u8[position + 1];
this._position = position + 2;
return this._littleEndian ? (b << 8) | a : (a << 8) | b;
}
readInt(): number /*int*/ {
const u8 = this._u8;
const position = this._position;
if (position + 4 > this._length) {
assert((<any> this).sec);
(<any> this).sec.throwError('flash.errors.EOFError', Errors.EOFError);
}
const a = u8[position + 0];
const b = u8[position + 1];
const c = u8[position + 2];
const d = u8[position + 3];
this._position = position + 4;
return this._littleEndian ?
(d << 24) | (c << 16) | (b << 8) | a :
(a << 24) | (b << 16) | (c << 8) | d;
}
readUnsignedInt(): number /*uint*/ {
return this.readInt() >>> 0;
}
readFloat(): number {
const position = this._position;
if (position + 4 > this._length) {
assert((<any> this).sec);
(<any> this).sec.throwError('flash.errors.EOFError', Errors.EOFError);
}
this._position = position + 4;
this._requestViews(TypedArrayViewFlags.F32);
if (this._littleEndian && (position & 0x3) === 0 && this._f32) {
return this._f32[position >> 2];
} else {
const u8 = this._u8;
const t8 = IntegerUtilities.u8;
if (this._littleEndian) {
t8[0] = u8[position + 0];
t8[1] = u8[position + 1];
t8[2] = u8[position + 2];
t8[3] = u8[position + 3];
} else {
t8[3] = u8[position + 0];
t8[2] = u8[position + 1];
t8[1] = u8[position + 2];
t8[0] = u8[position + 3];
}
return IntegerUtilities.f32[0];
}
}
readDouble(): number {
const u8 = this._u8;
const position = this._position;
if (position + 8 > this._length) {
assert((<any> this).sec);
(<any> this).sec.throwError('flash.errors.EOFError', Errors.EOFError);
}
const t8 = IntegerUtilities.u8;
if (this._littleEndian) {
t8[0] = u8[position + 0];
t8[1] = u8[position + 1];
t8[2] = u8[position + 2];
t8[3] = u8[position + 3];
t8[4] = u8[position + 4];
t8[5] = u8[position + 5];
t8[6] = u8[position + 6];
t8[7] = u8[position + 7];
} else {
t8[0] = u8[position + 7];
t8[1] = u8[position + 6];
t8[2] = u8[position + 5];
t8[3] = u8[position + 4];
t8[4] = u8[position + 3];
t8[5] = u8[position + 2];
t8[6] = u8[position + 1];
t8[7] = u8[position + 0];
}
this._position = position + 8;
return IntegerUtilities.f64[0];
}
writeBoolean(value: boolean): void {
this.writeByte(value ? 1 : 0);
}
writeByte(value: number /*int*/): void {
const length = this._position + 1;
this._ensureCapacity(length);
this._u8[this._position++] = value;
if (length > this._length) {
this._length = length;
}
}
writeUnsignedByte(value: number /*uint*/): void {
const length = this._position + 1;
this._ensureCapacity(length);
this._u8[this._position++] = value;
if (length > this._length) {
this._length = length;
}
}
writeRawBytes(bytes: Uint8Array): void {
const length = this._position + bytes.length;
this._ensureCapacity(length);
this._u8.set(bytes, this._position);
this._position = length;
if (length > this._length) {
this._length = length;
}
}
writeBytes(bytes: DataBuffer, offset?: number /*uint*/, length?: number /*uint*/): void {
if (isNullOrUndefined(bytes)) {
assert((<any> this).sec);
(<any> this).sec.throwError('TypeError', Errors.NullPointerError, 'bytes');
}
offset = offset >>> 0;
length = length >>> 0;
if (arguments.length < 2) {
offset = 0;
}
if (arguments.length < 3) {
length = 0;
}
if (offset !== clamp(offset, 0, bytes.length) ||
offset + length !== clamp(offset + length, 0, bytes.length)) {
assert((<any> this).sec);
(<any> this).sec.throwError('RangeError', Errors.ParamRangeError);
}
if (length === 0) {
length = bytes.length - offset;
}
this.writeRawBytes(new Uint8Array(bytes._buffer, offset, length));
}
writeShort(value: number /*int*/): void {
this.writeUnsignedShort(value);
}
writeUnsignedShort(value: number /*uint*/): void {
let position = this._position;
this._ensureCapacity(position + 2);
const u8 = this._u8;
if (this._littleEndian) {
u8[position + 0] = value;
u8[position + 1] = value >> 8;
} else {
u8[position + 0] = value >> 8;
u8[position + 1] = value;
}
position += 2;
this._position = position;
if (position > this._length) {
this._length = position;
}
}
writeInt(value: number /*int*/): void {
this.writeUnsignedInt(value);
}
write2Ints(a: number, b: number): void {
this.write2UnsignedInts(a, b);
}
write4Ints(a: number, b: number, c: number, d: number): void {
this.write4UnsignedInts(a, b, c, d);
}
writeUnsignedInt(value: number /*uint*/): void {
let position = this._position;
this._ensureCapacity(position + 4);
this._requestViews(TypedArrayViewFlags.I32);
if (this._littleEndian === DataBuffer._nativeLittleEndian && (position & 0x3) === 0 && this._i32) {
this._i32[position >> 2] = value;
} else {
const u8 = this._u8;
if (this._littleEndian) {
u8[position + 0] = value;
u8[position + 1] = value >> 8;
u8[position + 2] = value >> 16;
u8[position + 3] = value >> 24;
} else {
u8[position + 0] = value >> 24;
u8[position + 1] = value >> 16;
u8[position + 2] = value >> 8;
u8[position + 3] = value;
}
}
position += 4;
this._position = position;
if (position > this._length) {
this._length = position;
}
}
write2UnsignedInts(a: number, b: number): void {
let position = this._position;
this._ensureCapacity(position + 8);
this._requestViews(TypedArrayViewFlags.I32);
if (this._littleEndian === DataBuffer._nativeLittleEndian && (position & 0x3) === 0 && this._i32) {
this._i32[(position >> 2) + 0] = a;
this._i32[(position >> 2) + 1] = b;
position += 8;
this._position = position;
if (position > this._length) {
this._length = position;
}
} else {
this.writeUnsignedInt(a);
this.writeUnsignedInt(b);
}
}
write4UnsignedInts(a: number, b: number, c: number, d: number): void {
let position = this._position;
this._ensureCapacity(position + 16);
this._requestViews(TypedArrayViewFlags.I32);
if (this._littleEndian === DataBuffer._nativeLittleEndian && (position & 0x3) === 0 && this._i32) {
this._i32[(position >> 2) + 0] = a;
this._i32[(position >> 2) + 1] = b;
this._i32[(position >> 2) + 2] = c;
this._i32[(position >> 2) + 3] = d;
position += 16;
this._position = position;
if (position > this._length) {
this._length = position;
}
} else {
this.writeUnsignedInt(a);
this.writeUnsignedInt(b);
this.writeUnsignedInt(c);
this.writeUnsignedInt(d);
}
}
writeFloat(value: number): void {
let position = this._position;
this._ensureCapacity(position + 4);
this._requestViews(TypedArrayViewFlags.F32);
if (this._littleEndian === DataBuffer._nativeLittleEndian && (position & 0x3) === 0 && this._f32) {
this._f32[position >> 2] = value;
} else {
const u8 = this._u8;
IntegerUtilities.f32[0] = value;
const t8 = IntegerUtilities.u8;
if (this._littleEndian) {
u8[position + 0] = t8[0];
u8[position + 1] = t8[1];
u8[position + 2] = t8[2];
u8[position + 3] = t8[3];
} else {
u8[position + 0] = t8[3];
u8[position + 1] = t8[2];
u8[position + 2] = t8[1];
u8[position + 3] = t8[0];
}
}
position += 4;
this._position = position;
if (position > this._length) {
this._length = position;
}
}
write2Floats(a: number, b: number): void {
let position = this._position;
this._ensureCapacity(position + 8);
this._requestViews(TypedArrayViewFlags.F32);
if (this._littleEndian === DataBuffer._nativeLittleEndian && (position & 0x3) === 0 && this._f32) {
this._f32[(position >> 2) + 0] = a;
this._f32[(position >> 2) + 1] = b;
position += 8;
this._position = position;
if (position > this._length) {
this._length = position;
}
} else {
this.writeFloat(a);
this.writeFloat(b);
}
}
write6Floats(a: number, b: number, c: number, d: number, e: number, f: number): void {
let position = this._position;
this._ensureCapacity(position + 24);
this._requestViews(TypedArrayViewFlags.F32);
if (this._littleEndian === DataBuffer._nativeLittleEndian && (position & 0x3) === 0 && this._f32) {
this._f32[(position >> 2) + 0] = a;
this._f32[(position >> 2) + 1] = b;
this._f32[(position >> 2) + 2] = c;
this._f32[(position >> 2) + 3] = d;
this._f32[(position >> 2) + 4] = e;
this._f32[(position >> 2) + 5] = f;
position += 24;
this._position = position;
if (position > this._length) {
this._length = position;
}
} else {
this.writeFloat(a);
this.writeFloat(b);
this.writeFloat(c);
this.writeFloat(d);
this.writeFloat(e);
this.writeFloat(f);
}
}
writeDouble(value: number): void {
let position = this._position;
this._ensureCapacity(position + 8);
const u8 = this._u8;
IntegerUtilities.f64[0] = value;
const t8 = IntegerUtilities.u8;
if (this._littleEndian) {
u8[position + 0] = t8[0];
u8[position + 1] = t8[1];
u8[position + 2] = t8[2];
u8[position + 3] = t8[3];
u8[position + 4] = t8[4];
u8[position + 5] = t8[5];
u8[position + 6] = t8[6];
u8[position + 7] = t8[7];
} else {
u8[position + 0] = t8[7];
u8[position + 1] = t8[6];
u8[position + 2] = t8[5];
u8[position + 3] = t8[4];
u8[position + 4] = t8[3];
u8[position + 5] = t8[2];
u8[position + 6] = t8[1];
u8[position + 7] = t8[0];
}
position += 8;
this._position = position;
if (position > this._length) {
this._length = position;
}
}
readRawBytes(): Int8Array {
return new Int8Array(this._buffer, 0, this._length);
}
writeUTF(value: string): void {
value = axCoerceString(value);
const bytes = utf8decode(value);
this.writeShort(bytes.length);
this.writeRawBytes(bytes);
}
writeUTFBytes(value: string): void {
value = axCoerceString(value);
const bytes = utf8decode(value);
this.writeRawBytes(bytes);
}
readUTF(): string {
return this.readUTFBytes(this.readShort());
}
readUTFBytes(length: number /*uint*/): string {
length = length >>> 0;
const pos = this._position;
if (pos + length > this._length) {
assert((<any> this).sec);
(<any> this).sec.throwError('flash.errors.EOFError', Errors.EOFError);
}
this._position += length;
return utf8encode(new Uint8Array(this._buffer, pos, length));
}
get length(): number /*uint*/ {
return this._length;
}
set length(value: number /*uint*/) {
value = value >>> 0;
const capacity = this._buffer.byteLength;
/* XXX: Do we need to zero the difference if length <= cap? */
if (value > capacity) {
this._ensureCapacity(value);
}
this._length = value;
this._position = clamp(this._position, 0, this._length);
}
get bytesAvailable(): number /*uint*/ {
return this._length - this._position;
}
get position(): number /*uint*/ {
return this._position;
}
get buffer(): ArrayBuffer {
return this._buffer;
}
get bytes(): Uint8Array {
return this._u8;
}
get ints(): Int32Array {
this._requestViews(TypedArrayViewFlags.I32);
return this._i32;
}
set position(position: number /*uint*/) {
this._position = position >>> 0;
}
get objectEncoding(): number /*uint*/ {
return this._objectEncoding;
}
set objectEncoding(version: number /*uint*/) {
version = version >>> 0;
this._objectEncoding = version;
}
get endian(): string {
return this._littleEndian ? 'littleEndian' : 'bigEndian';
}
set endian(type: string) {
type = axCoerceString(type);
if (type === 'auto') {
this._littleEndian = DataBuffer._nativeLittleEndian;
} else {
this._littleEndian = type === 'littleEndian';
}
}
toString(): string {
return utf8encode(new Uint8Array(this._buffer, 0, this._length));
}
toBlob(type: string): Blob {
return new Blob([new Uint8Array(this._buffer, this._position, this._length)], { type: type });
}
writeMultiByte(value: string, charSet: string): void {
value = axCoerceString(value);
charSet = axCoerceString(charSet);
if (charSet == 'UTF-8') {
const bytes = utf8decode(value);
this.writeRawBytes(bytes);
} else {
console.log('packageInternal flash.utils.ObjectOutput::writeMultiByte only encoding supported is UTF-8');
}
}
readMultiByte(length: number /*uint*/, charSet: string): string {
length = length >>> 0; charSet = axCoerceString(charSet);
console.log('packageInternal flash.utils.ObjectInput::readMultiByte'); return;
}
getValue(name: number): any {
name = name | 0;
if (name >= this._length) {
return undefined;
}
return this._u8[name];
}
setValue(name: number, value: any) {
name = name | 0;
const length = name + 1;
this._ensureCapacity(length);
this._u8[name] = value;
if (length > this._length) {
this._length = length;
}
}
readFixed(): number {
return this.readInt() / 65536;
}
readFixed8(): number {
return this.readShort() / 256;
}
readFloat16(): number {
const uint16 = this.readUnsignedShort();
const sign = uint16 >> 15 ? -1 : 1;
const exponent = (uint16 & 0x7c00) >> 10;
const fraction = uint16 & 0x03ff;
if (!exponent) {
return sign * Math.pow(2, -14) * (fraction / 1024);
}
if (exponent === 0x1f) {
return fraction ? NaN : sign * Infinity;
}
return sign * Math.pow(2, exponent - 15) * (1 + (fraction / 1024));
}
readEncodedU32(): number {
let value = this.readUnsignedByte();
if (!(value & 0x080)) {
return value;
}
value = (value & 0x7f) | this.readUnsignedByte() << 7;
if (!(value & 0x4000)) {
return value;
}
value = (value & 0x3fff) | this.readUnsignedByte() << 14;
if (!(value & 0x200000)) {
return value;
}
value = (value & 0x1FFFFF) | this.readUnsignedByte() << 21;
if (!(value & 0x10000000)) {
return value;
}
return (value & 0xFFFFFFF) | (this.readUnsignedByte() << 28);
}
readBits(size: number): number {
return (this.readUnsignedBits(size) << (32 - size)) >> (32 - size);
}
readUnsignedBits(size: number): number {
let buffer = this._bitBuffer;
let length = this._bitLength;
while (size > length) {
buffer = (buffer << 8) | this.readUnsignedByte();
length += 8;
}
length -= size;
const value = (buffer >>> length) & bitMasks[size];
this._bitBuffer = buffer;
this._bitLength = length;
return value;
}
readFixedBits(size: number): number {
return this.readBits(size) / 65536;
}
readString(length?: number): string {
const position = this._position;
if (length) {
if (position + length > this._length) {
assert((<any> this).sec);
(<any> this).sec.throwError('flash.errors.EOFError', Errors.EOFError);
}
this._position += length;
} else {
length = 0;
for (let i = position; i < this._length && this._u8[i]; i++) {
length++;
}
this._position += length + 1;
}
return utf8encode(new Uint8Array(this._buffer, position, length));
}
align() {
this._bitBuffer = 0;
this._bitLength = 0;
}
deflate() {
this.compress('deflate');
}
inflate() {
this.uncompress('deflate');
}
compress(algorithm: string): void {
if (arguments.length === 0) {
algorithm = 'zlib';
} else {
algorithm = axCoerceString(algorithm);
}
let deflate: Deflate;
switch (algorithm) {
case 'zlib':
deflate = new Deflate(true);
break;
case 'deflate':
deflate = new Deflate(false);
break;
default:
return;
}
const output = new DataBuffer();
deflate.onData = output.writeRawBytes.bind(output);
deflate.push(this._u8.subarray(0, this._length));
deflate.close();
this._ensureCapacity(output._u8.length);
this._u8.set(output._u8);
this.length = output.length;
this._position = 0;
}
uncompress(algorithm: string): void {
if (arguments.length === 0) {
algorithm = 'zlib';
} else {
algorithm = axCoerceString(algorithm);
}
let inflate: IDataDecoder;
switch (algorithm) {
case 'zlib':
inflate = Inflate.create(true);
break;
case 'deflate':
inflate = Inflate.create(false);
break;
case 'lzma':
inflate = new LzmaDecoder(false);
break;
default:
return;
}
const output = new DataBuffer();
let error;
inflate.onData = output.writeRawBytes.bind(output);
inflate.onError = (e) => error = e;
inflate.push(this._u8.subarray(0, this._length));
if (error) {
assert((<any> this).sec);
(<any> this).sec.throwError('IOError', Errors.CompressedDataError);
}
inflate.close();
this._ensureCapacity(output._u8.length);
this._u8.set(output._u8);
this.length = output.length;
this._position = 0;
}
}