113 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| var _LineDecoder_buffer, _LineDecoder_carriageReturnIndex;
 | |
| Object.defineProperty(exports, "__esModule", { value: true });
 | |
| exports.LineDecoder = void 0;
 | |
| exports.findDoubleNewlineIndex = findDoubleNewlineIndex;
 | |
| const tslib_1 = require("../tslib.js");
 | |
| const bytes_1 = require("../utils/bytes.js");
 | |
| /**
 | |
|  * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally
 | |
|  * reading lines from text.
 | |
|  *
 | |
|  * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258
 | |
|  */
 | |
| class LineDecoder {
 | |
|     constructor() {
 | |
|         _LineDecoder_buffer.set(this, void 0);
 | |
|         _LineDecoder_carriageReturnIndex.set(this, void 0);
 | |
|         tslib_1.__classPrivateFieldSet(this, _LineDecoder_buffer, new Uint8Array(), "f");
 | |
|         tslib_1.__classPrivateFieldSet(this, _LineDecoder_carriageReturnIndex, null, "f");
 | |
|     }
 | |
|     decode(chunk) {
 | |
|         if (chunk == null) {
 | |
|             return [];
 | |
|         }
 | |
|         const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk)
 | |
|             : typeof chunk === 'string' ? (0, bytes_1.encodeUTF8)(chunk)
 | |
|                 : chunk;
 | |
|         tslib_1.__classPrivateFieldSet(this, _LineDecoder_buffer, (0, bytes_1.concatBytes)([tslib_1.__classPrivateFieldGet(this, _LineDecoder_buffer, "f"), binaryChunk]), "f");
 | |
|         const lines = [];
 | |
|         let patternIndex;
 | |
|         while ((patternIndex = findNewlineIndex(tslib_1.__classPrivateFieldGet(this, _LineDecoder_buffer, "f"), tslib_1.__classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f"))) != null) {
 | |
|             if (patternIndex.carriage && tslib_1.__classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f") == null) {
 | |
|                 // skip until we either get a corresponding `\n`, a new `\r` or nothing
 | |
|                 tslib_1.__classPrivateFieldSet(this, _LineDecoder_carriageReturnIndex, patternIndex.index, "f");
 | |
|                 continue;
 | |
|             }
 | |
|             // we got double \r or \rtext\n
 | |
|             if (tslib_1.__classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f") != null &&
 | |
|                 (patternIndex.index !== tslib_1.__classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f") + 1 || patternIndex.carriage)) {
 | |
|                 lines.push((0, bytes_1.decodeUTF8)(tslib_1.__classPrivateFieldGet(this, _LineDecoder_buffer, "f").subarray(0, tslib_1.__classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f") - 1)));
 | |
|                 tslib_1.__classPrivateFieldSet(this, _LineDecoder_buffer, tslib_1.__classPrivateFieldGet(this, _LineDecoder_buffer, "f").subarray(tslib_1.__classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f")), "f");
 | |
|                 tslib_1.__classPrivateFieldSet(this, _LineDecoder_carriageReturnIndex, null, "f");
 | |
|                 continue;
 | |
|             }
 | |
|             const endIndex = tslib_1.__classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f") !== null ? patternIndex.preceding - 1 : patternIndex.preceding;
 | |
|             const line = (0, bytes_1.decodeUTF8)(tslib_1.__classPrivateFieldGet(this, _LineDecoder_buffer, "f").subarray(0, endIndex));
 | |
|             lines.push(line);
 | |
|             tslib_1.__classPrivateFieldSet(this, _LineDecoder_buffer, tslib_1.__classPrivateFieldGet(this, _LineDecoder_buffer, "f").subarray(patternIndex.index), "f");
 | |
|             tslib_1.__classPrivateFieldSet(this, _LineDecoder_carriageReturnIndex, null, "f");
 | |
|         }
 | |
|         return lines;
 | |
|     }
 | |
|     flush() {
 | |
|         if (!tslib_1.__classPrivateFieldGet(this, _LineDecoder_buffer, "f").length) {
 | |
|             return [];
 | |
|         }
 | |
|         return this.decode('\n');
 | |
|     }
 | |
| }
 | |
| exports.LineDecoder = LineDecoder;
 | |
| _LineDecoder_buffer = new WeakMap(), _LineDecoder_carriageReturnIndex = new WeakMap();
 | |
| // prettier-ignore
 | |
| LineDecoder.NEWLINE_CHARS = new Set(['\n', '\r']);
 | |
| LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g;
 | |
| /**
 | |
|  * This function searches the buffer for the end patterns, (\r or \n)
 | |
|  * and returns an object with the index preceding the matched newline and the
 | |
|  * index after the newline char. `null` is returned if no new line is found.
 | |
|  *
 | |
|  * ```ts
 | |
|  * findNewLineIndex('abc\ndef') -> { preceding: 2, index: 3 }
 | |
|  * ```
 | |
|  */
 | |
| function findNewlineIndex(buffer, startIndex) {
 | |
|     const newline = 0x0a; // \n
 | |
|     const carriage = 0x0d; // \r
 | |
|     for (let i = startIndex ?? 0; i < buffer.length; i++) {
 | |
|         if (buffer[i] === newline) {
 | |
|             return { preceding: i, index: i + 1, carriage: false };
 | |
|         }
 | |
|         if (buffer[i] === carriage) {
 | |
|             return { preceding: i, index: i + 1, carriage: true };
 | |
|         }
 | |
|     }
 | |
|     return null;
 | |
| }
 | |
| function findDoubleNewlineIndex(buffer) {
 | |
|     // This function searches the buffer for the end patterns (\r\r, \n\n, \r\n\r\n)
 | |
|     // and returns the index right after the first occurrence of any pattern,
 | |
|     // or -1 if none of the patterns are found.
 | |
|     const newline = 0x0a; // \n
 | |
|     const carriage = 0x0d; // \r
 | |
|     for (let i = 0; i < buffer.length - 1; i++) {
 | |
|         if (buffer[i] === newline && buffer[i + 1] === newline) {
 | |
|             // \n\n
 | |
|             return i + 2;
 | |
|         }
 | |
|         if (buffer[i] === carriage && buffer[i + 1] === carriage) {
 | |
|             // \r\r
 | |
|             return i + 2;
 | |
|         }
 | |
|         if (buffer[i] === carriage &&
 | |
|             buffer[i + 1] === newline &&
 | |
|             i + 3 < buffer.length &&
 | |
|             buffer[i + 2] === carriage &&
 | |
|             buffer[i + 3] === newline) {
 | |
|             // \r\n\r\n
 | |
|             return i + 4;
 | |
|         }
 | |
|     }
 | |
|     return -1;
 | |
| }
 | |
| //# sourceMappingURL=line.js.map
 |