--- /dev/null
+"use strict";
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.AbstractMessageBuffer = void 0;
+const CR = 13;
+const LF = 10;
+const CRLF = '\r\n';
+class AbstractMessageBuffer {
+ constructor(encoding = 'utf-8') {
+ this._encoding = encoding;
+ this._chunks = [];
+ this._totalLength = 0;
+ }
+ get encoding() {
+ return this._encoding;
+ }
+ append(chunk) {
+ const toAppend = typeof chunk === 'string' ? this.fromString(chunk, this._encoding) : chunk;
+ this._chunks.push(toAppend);
+ this._totalLength += toAppend.byteLength;
+ }
+ tryReadHeaders() {
+ if (this._chunks.length === 0) {
+ return undefined;
+ }
+ let state = 0;
+ let chunkIndex = 0;
+ let offset = 0;
+ let chunkBytesRead = 0;
+ row: while (chunkIndex < this._chunks.length) {
+ const chunk = this._chunks[chunkIndex];
+ offset = 0;
+ column: while (offset < chunk.length) {
+ const value = chunk[offset];
+ switch (value) {
+ case CR:
+ switch (state) {
+ case 0:
+ state = 1;
+ break;
+ case 2:
+ state = 3;
+ break;
+ default:
+ state = 0;
+ }
+ break;
+ case LF:
+ switch (state) {
+ case 1:
+ state = 2;
+ break;
+ case 3:
+ state = 4;
+ offset++;
+ break row;
+ default:
+ state = 0;
+ }
+ break;
+ default:
+ state = 0;
+ }
+ offset++;
+ }
+ chunkBytesRead += chunk.byteLength;
+ chunkIndex++;
+ }
+ if (state !== 4) {
+ return undefined;
+ }
+ // The buffer contains the two CRLF at the end. So we will
+ // have two empty lines after the split at the end as well.
+ const buffer = this._read(chunkBytesRead + offset);
+ const result = new Map();
+ const headers = this.toString(buffer, 'ascii').split(CRLF);
+ if (headers.length < 2) {
+ return result;
+ }
+ for (let i = 0; i < headers.length - 2; i++) {
+ const header = headers[i];
+ const index = header.indexOf(':');
+ if (index === -1) {
+ throw new Error('Message header must separate key and value using :');
+ }
+ const key = header.substr(0, index);
+ const value = header.substr(index + 1).trim();
+ result.set(key, value);
+ }
+ return result;
+ }
+ tryReadBody(length) {
+ if (this._totalLength < length) {
+ return undefined;
+ }
+ return this._read(length);
+ }
+ get numberOfBytes() {
+ return this._totalLength;
+ }
+ _read(byteCount) {
+ if (byteCount === 0) {
+ return this.emptyBuffer();
+ }
+ if (byteCount > this._totalLength) {
+ throw new Error(`Cannot read so many bytes!`);
+ }
+ if (this._chunks[0].byteLength === byteCount) {
+ // super fast path, precisely first chunk must be returned
+ const chunk = this._chunks[0];
+ this._chunks.shift();
+ this._totalLength -= byteCount;
+ return this.asNative(chunk);
+ }
+ if (this._chunks[0].byteLength > byteCount) {
+ // fast path, the reading is entirely within the first chunk
+ const chunk = this._chunks[0];
+ const result = this.asNative(chunk, byteCount);
+ this._chunks[0] = chunk.slice(byteCount);
+ this._totalLength -= byteCount;
+ return result;
+ }
+ const result = this.allocNative(byteCount);
+ let resultOffset = 0;
+ let chunkIndex = 0;
+ while (byteCount > 0) {
+ const chunk = this._chunks[chunkIndex];
+ if (chunk.byteLength > byteCount) {
+ // this chunk will survive
+ const chunkPart = chunk.slice(0, byteCount);
+ result.set(chunkPart, resultOffset);
+ resultOffset += byteCount;
+ this._chunks[chunkIndex] = chunk.slice(byteCount);
+ this._totalLength -= byteCount;
+ byteCount -= byteCount;
+ }
+ else {
+ // this chunk will be entirely read
+ result.set(chunk, resultOffset);
+ resultOffset += chunk.byteLength;
+ this._chunks.shift();
+ this._totalLength -= chunk.byteLength;
+ byteCount -= chunk.byteLength;
+ }
+ }
+ return result;
+ }
+}
+exports.AbstractMessageBuffer = AbstractMessageBuffer;
+//# sourceMappingURL=messageBuffer.js.map
\ No newline at end of file