UNPKG

detritus-client-socket

Version:

A TypeScript NodeJS library to interact with Discord's Gateway

176 lines (175 loc) 5.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ZlibDecompressor = void 0; const detritus_utils_1 = require("detritus-utils"); const errors_1 = require("../errors"); const DependencyTypes = Object.freeze({ PAKO: 'pako', ZLIB: 'zlib', }); const ErrorCodes = Object.freeze({ ERR_ZLIB_BINDING_CLOSED: 'ERR_ZLIB_BINDING_CLOSED', }); const Inflate = { flushCode: 0, module: require(DependencyTypes.ZLIB), type: DependencyTypes.ZLIB, }; Inflate.flushCode = Inflate.module.constants.Z_SYNC_FLUSH; for (let type of [DependencyTypes.PAKO]) { try { Inflate.module = require(type); Inflate.type = type; } catch (e) { } } class ZlibDecompressor extends detritus_utils_1.EventSpewer { constructor(suffix, chunkSize = 64 * 1024) { super(); this.dataChunks = []; this.chunks = []; this.closed = false; this.flushing = false; this.inflate = null; this.chunkSize = chunkSize; this.suffix = suffix; this.initialize(); } close() { this.closed = true; this.chunks.length = 0; this.dataChunks.length = 0; this.flushing = false; if (this.inflate) { switch (Inflate.type) { case DependencyTypes.ZLIB: { this.inflate.close(); this.inflate.removeAllListeners(); } ; break; } } this.inflate = null; } feed(chunk) { if (!this.closed && this.inflate) { this.chunks.push(chunk); this.write(); } } initialize() { this.close(); switch (Inflate.type) { case DependencyTypes.PAKO: { this.inflate = new Inflate.module.Inflate({ chunkSize: this.chunkSize, }); } ; break; case DependencyTypes.ZLIB: { this.inflate = Inflate.module.createInflate({ chunkSize: this.chunkSize, flush: Inflate.flushCode, }); this.inflate.on('data', this.onData.bind(this)); this.inflate.on('error', this.onError.bind(this)); } ; break; default: { throw new Error(`Unable to use any ${JSON.stringify(Object.values(DependencyTypes))}`); } ; } this.closed = false; } reset() { this.initialize(); } write() { if ((this.closed) || (!this.inflate) || (!this.chunks.length) || (this.flushing)) { return; } const chunk = this.chunks.shift(); const isEnd = ((this.suffix.length <= chunk.length) && (chunk.slice(-this.suffix.length).equals(this.suffix))); switch (Inflate.type) { case DependencyTypes.PAKO: { this.inflate.push(chunk, isEnd && Inflate.flushCode); if (isEnd) { if (this.inflate.err) { const error = new errors_1.InflateError(this.inflate.msg, this.inflate.err); this.onError(error); } else { this.onData(this.inflate.result); } } } ; break; case DependencyTypes.ZLIB: { this.inflate.write(chunk); if (isEnd) { this.flushing = true; this.inflate.flush(Inflate.flushCode, this.onFlush.bind(this)); return; } } ; break; } this.write(); } onData(data) { switch (Inflate.type) { case DependencyTypes.PAKO: { this.emit('data', Buffer.from(data)); } ; break; case DependencyTypes.ZLIB: { this.dataChunks.push(data); } ; break; } } onError(error) { if (error.code === ErrorCodes.ERR_ZLIB_BINDING_CLOSED) { // zlib was flushing when we called .close on it return; } this.emit('error', error); } onFlush(error) { if (error) { return; } if (this.dataChunks.length) { const chunk = (this.dataChunks.length === 1) ? this.dataChunks.shift() : Buffer.concat(this.dataChunks); this.dataChunks.length = 0; this.emit('data', chunk); } this.flushing = false; this.write(); } on(event, listener) { super.on(event, listener); return this; } } exports.ZlibDecompressor = ZlibDecompressor;