UNPKG

3.75 kBJavaScriptView Raw
1"use strict";
2
3let assert = require("assert").ok;
4let zlib = require("zlib");
5let util = require("util");
6
7let kMaxLength = require("buffer").kMaxLength;
8
9function Inflate(opts) {
10 if (!(this instanceof Inflate)) {
11 return new Inflate(opts);
12 }
13
14 if (opts && opts.chunkSize < zlib.Z_MIN_CHUNK) {
15 opts.chunkSize = zlib.Z_MIN_CHUNK;
16 }
17
18 zlib.Inflate.call(this, opts);
19
20 // Node 8 --> 9 compatibility check
21 this._offset = this._offset === undefined ? this._outOffset : this._offset;
22 this._buffer = this._buffer || this._outBuffer;
23
24 if (opts && opts.maxLength != null) {
25 this._maxLength = opts.maxLength;
26 }
27}
28
29function createInflate(opts) {
30 return new Inflate(opts);
31}
32
33function _close(engine, callback) {
34 if (callback) {
35 process.nextTick(callback);
36 }
37
38 // Caller may invoke .close after a zlib error (which will null _handle).
39 if (!engine._handle) {
40 return;
41 }
42
43 engine._handle.close();
44 engine._handle = null;
45}
46
47Inflate.prototype._processChunk = function (chunk, flushFlag, asyncCb) {
48 if (typeof asyncCb === "function") {
49 return zlib.Inflate._processChunk.call(this, chunk, flushFlag, asyncCb);
50 }
51
52 let self = this;
53
54 let availInBefore = chunk && chunk.length;
55 let availOutBefore = this._chunkSize - this._offset;
56 let leftToInflate = this._maxLength;
57 let inOff = 0;
58
59 let buffers = [];
60 let nread = 0;
61
62 let error;
63 this.on("error", function (err) {
64 error = err;
65 });
66
67 function handleChunk(availInAfter, availOutAfter) {
68 if (self._hadError) {
69 return;
70 }
71
72 let have = availOutBefore - availOutAfter;
73 assert(have >= 0, "have should not go down");
74
75 if (have > 0) {
76 let out = self._buffer.slice(self._offset, self._offset + have);
77 self._offset += have;
78
79 if (out.length > leftToInflate) {
80 out = out.slice(0, leftToInflate);
81 }
82
83 buffers.push(out);
84 nread += out.length;
85 leftToInflate -= out.length;
86
87 if (leftToInflate === 0) {
88 return false;
89 }
90 }
91
92 if (availOutAfter === 0 || self._offset >= self._chunkSize) {
93 availOutBefore = self._chunkSize;
94 self._offset = 0;
95 self._buffer = Buffer.allocUnsafe(self._chunkSize);
96 }
97
98 if (availOutAfter === 0) {
99 inOff += availInBefore - availInAfter;
100 availInBefore = availInAfter;
101
102 return true;
103 }
104
105 return false;
106 }
107
108 assert(this._handle, "zlib binding closed");
109 let res;
110 do {
111 res = this._handle.writeSync(
112 flushFlag,
113 chunk, // in
114 inOff, // in_off
115 availInBefore, // in_len
116 this._buffer, // out
117 this._offset, //out_off
118 availOutBefore
119 ); // out_len
120 // Node 8 --> 9 compatibility check
121 res = res || this._writeState;
122 } while (!this._hadError && handleChunk(res[0], res[1]));
123
124 if (this._hadError) {
125 throw error;
126 }
127
128 if (nread >= kMaxLength) {
129 _close(this);
130 throw new RangeError(
131 "Cannot create final Buffer. It would be larger than 0x" +
132 kMaxLength.toString(16) +
133 " bytes"
134 );
135 }
136
137 let buf = Buffer.concat(buffers, nread);
138 _close(this);
139
140 return buf;
141};
142
143util.inherits(Inflate, zlib.Inflate);
144
145function zlibBufferSync(engine, buffer) {
146 if (typeof buffer === "string") {
147 buffer = Buffer.from(buffer);
148 }
149 if (!(buffer instanceof Buffer)) {
150 throw new TypeError("Not a string or buffer");
151 }
152
153 let flushFlag = engine._finishFlushFlag;
154 if (flushFlag == null) {
155 flushFlag = zlib.Z_FINISH;
156 }
157
158 return engine._processChunk(buffer, flushFlag);
159}
160
161function inflateSync(buffer, opts) {
162 return zlibBufferSync(new Inflate(opts), buffer);
163}
164
165module.exports = exports = inflateSync;
166exports.Inflate = Inflate;
167exports.createInflate = createInflate;
168exports.inflateSync = inflateSync;