UNPKG

nstdlib-nightly

Version:

Node.js standard library converted to runtime-agnostic ES modules.

162 lines (151 loc) 5.05 kB
// Source: https://github.com/nodejs/node/blob/65eff1eb/lib/string_decoder.js import { Buffer } from "nstdlib/lib/buffer"; import { kIncompleteCharactersStart, kIncompleteCharactersEnd, kMissingBytes, kBufferedBytes, kEncodingField, kSize, decode, flush, } from "nstdlib/stub/binding/string_decoder"; import { kIsEncodingSymbol, encodingsMap, normalizeEncoding as _normalizeEncoding, } from "nstdlib/lib/internal/util"; import { codes as __codes__ } from "nstdlib/lib/internal/errors"; // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. const { ERR_INVALID_ARG_TYPE, ERR_INVALID_THIS, ERR_UNKNOWN_ENCODING } = __codes__; const isEncoding = Buffer[kIsEncodingSymbol]; const kNativeDecoder = Symbol("kNativeDecoder"); // Do not cache `Buffer.isEncoding` when checking encoding names as some // modules monkey-patch it to support additional encodings /** * Normalize encoding notation * @param {string} enc * @returns {"utf8" | "utf16le" | "hex" | "ascii" * | "base64" | "latin1" | "base64url"} * @throws {TypeError} Throws an error when encoding is invalid */ function normalizeEncoding(enc) { const nenc = _normalizeEncoding(enc); if (nenc === undefined) { if (Buffer.isEncoding === isEncoding || !Buffer.isEncoding(enc)) throw new ERR_UNKNOWN_ENCODING(enc); return enc; } return nenc; } /** * StringDecoder provides an interface for efficiently splitting a series of * buffers into a series of JS strings without breaking apart multi-byte * characters. * @param {string} [encoding=utf-8] */ function StringDecoder(encoding) { this.encoding = normalizeEncoding(encoding); this[kNativeDecoder] = Buffer.alloc(kSize); this[kNativeDecoder][kEncodingField] = encodingsMap[this.encoding]; } /** * Returns a decoded string, omitting any incomplete multi-bytes * characters at the end of the Buffer, or TypedArray, or DataView * @param {string | Buffer | TypedArray | DataView} buf * @returns {string} * @throws {TypeError} Throws when buf is not in one of supported types */ StringDecoder.prototype.write = function write(buf) { if (typeof buf === "string") return buf; if (!ArrayBuffer.isView(buf)) throw new ERR_INVALID_ARG_TYPE( "buf", ["Buffer", "TypedArray", "DataView"], buf, ); if (!this[kNativeDecoder]) { throw new ERR_INVALID_THIS("StringDecoder"); } return decode(this[kNativeDecoder], buf); }; /** * Returns any remaining input stored in the internal buffer as a string. * After end() is called, the stringDecoder object can be reused for new * input. * @param {string | Buffer | TypedArray | DataView} [buf] * @returns {string} */ StringDecoder.prototype.end = function end(buf) { let ret = ""; if (buf !== undefined) ret = this.write(buf); if (this[kNativeDecoder][kBufferedBytes] > 0) ret += flush(this[kNativeDecoder]); return ret; }; /* Everything below this line is undocumented legacy stuff. */ /** * * @param {string | Buffer | TypedArray | DataView} buf * @param {number} offset * @returns {string} */ StringDecoder.prototype.text = function text(buf, offset) { this[kNativeDecoder][kMissingBytes] = 0; this[kNativeDecoder][kBufferedBytes] = 0; return this.write(buf.slice(offset)); }; Object.defineProperties(StringDecoder.prototype, { lastChar: { __proto__: null, configurable: true, enumerable: true, get() { return TypedArrayPrototypeSubarray( this[kNativeDecoder], kIncompleteCharactersStart, kIncompleteCharactersEnd, ); }, }, lastNeed: { __proto__: null, configurable: true, enumerable: true, get() { return this[kNativeDecoder][kMissingBytes]; }, }, lastTotal: { __proto__: null, configurable: true, enumerable: true, get() { return ( this[kNativeDecoder][kBufferedBytes] + this[kNativeDecoder][kMissingBytes] ); }, }, }); export { StringDecoder };