@smithy/core
Advanced tools
@@ -1,2 +0,2 @@ | ||
| const { nv, toUtf8, fromUtf8, NumericValue, calculateBodyLength, _parseEpochTimestamp, fromBase64, generateIdempotencyToken } = require("@smithy/core/serde"); | ||
| const { nv, NumericValue, calculateBodyLength, _parseEpochTimestamp, fromBase64, generateIdempotencyToken } = require("@smithy/core/serde"); | ||
| const { HttpRequest, collectBody, SerdeContext, RpcProtocol } = require("@smithy/core/protocols"); | ||
@@ -32,10 +32,11 @@ const { NormalizedSchema, deref, TypeRegistry } = require("@smithy/core/schema"); | ||
| const USE_TEXT_DECODER = typeof TextDecoder !== "undefined"; | ||
| const USE_BUFFER$1 = typeof Buffer !== "undefined"; | ||
| const textDecoder = new TextDecoder(); | ||
| let payload = alloc(0); | ||
| let isBuffer = false; | ||
| let dataView$1 = new DataView(payload.buffer, payload.byteOffset, payload.byteLength); | ||
| const textDecoder = USE_TEXT_DECODER ? new TextDecoder() : null; | ||
| let _offset = 0; | ||
| function setPayload(bytes) { | ||
| payload = bytes; | ||
| isBuffer = USE_BUFFER$1 && payload instanceof Buffer; | ||
| dataView$1 = new DataView(payload.buffer, payload.byteOffset, payload.byteLength); | ||
@@ -49,6 +50,9 @@ } | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (minor === minorIndefinite && 2 <= major && major <= 5) { | ||
| return decodeIndefinite(at, to); | ||
| } | ||
| switch (major) { | ||
| case majorUint64: | ||
| case majorNegativeInt64: | ||
| case majorTag: | ||
| case majorTag: { | ||
| let unsignedInt; | ||
@@ -63,27 +67,39 @@ let offset; | ||
| case extendedOneByte: | ||
| if (to - at < 2) { | ||
| overflow(1); | ||
| } | ||
| unsignedInt = payload[at + 1]; | ||
| offset = 2; | ||
| break; | ||
| case extendedFloat16: | ||
| if (to - at < 3) { | ||
| overflow(2); | ||
| } | ||
| unsignedInt = dataView$1.getUint16(at + 1); | ||
| offset = 3; | ||
| break; | ||
| case extendedFloat32: | ||
| if (to - at < 5) { | ||
| overflow(4); | ||
| } | ||
| unsignedInt = dataView$1.getUint32(at + 1); | ||
| offset = 5; | ||
| break; | ||
| case extendedFloat64: | ||
| const countLength = minorValueToArgumentLength[minor]; | ||
| const countOffset = (countLength + 1); | ||
| offset = countOffset; | ||
| if (to - at < countOffset) { | ||
| throw new Error(`countLength ${countLength} greater than remaining buf len.`); | ||
| if (to - at < 9) { | ||
| overflow(8); | ||
| } | ||
| const countIndex = at + 1; | ||
| if (countLength === 1) { | ||
| unsignedInt = payload[countIndex]; | ||
| { | ||
| const hi = dataView$1.getUint32(at + 1); | ||
| if (hi < 0x00200000) { | ||
| unsignedInt = hi * 4294967296 + dataView$1.getUint32(at + 5); | ||
| } | ||
| else { | ||
| unsignedInt = dataView$1.getBigUint64(at + 1); | ||
| } | ||
| } | ||
| else if (countLength === 2) { | ||
| unsignedInt = dataView$1.getUint16(countIndex); | ||
| } | ||
| else if (countLength === 4) { | ||
| unsignedInt = dataView$1.getUint32(countIndex); | ||
| } | ||
| else { | ||
| unsignedInt = dataView$1.getBigUint64(countIndex); | ||
| } | ||
| offset = 9; | ||
| break; | ||
| default: | ||
| throw new Error(`unexpected minor value ${minor}.`); | ||
| unexpectedMinor(minor); | ||
| } | ||
@@ -107,69 +123,13 @@ } | ||
| else { | ||
| if (minor === 2 || minor === 3) { | ||
| const length = decodeCount(at + offset, to); | ||
| let b = BigInt(0); | ||
| const start = at + offset + _offset; | ||
| for (let i = start; i < start + length; ++i) { | ||
| b = (b << BigInt(8)) | BigInt(payload[i]); | ||
| } | ||
| _offset = offset + _offset + length; | ||
| return minor === 3 ? -b - BigInt(1) : b; | ||
| } | ||
| else if (minor === 4) { | ||
| const decimalFraction = decode(at + offset, to); | ||
| const [exponent, mantissa] = decimalFraction; | ||
| const normalizer = mantissa < 0 ? -1 : 1; | ||
| const mantissaStr = "0".repeat(Math.abs(exponent) + 1) + String(BigInt(normalizer) * BigInt(mantissa)); | ||
| let numericString; | ||
| const sign = mantissa < 0 ? "-" : ""; | ||
| numericString = | ||
| exponent === 0 | ||
| ? mantissaStr | ||
| : mantissaStr.slice(0, mantissaStr.length + exponent) + "." + mantissaStr.slice(exponent); | ||
| numericString = numericString.replace(/^0+/g, ""); | ||
| if (numericString === "") { | ||
| numericString = "0"; | ||
| } | ||
| if (numericString[0] === ".") { | ||
| numericString = "0" + numericString; | ||
| } | ||
| numericString = sign + numericString; | ||
| _offset = offset + _offset; | ||
| return nv(numericString); | ||
| } | ||
| else { | ||
| const value = decode(at + offset, to); | ||
| const valueOffset = _offset; | ||
| _offset = offset + valueOffset; | ||
| return tag({ tag: castBigInt(unsignedInt), value }); | ||
| } | ||
| return decodeTagValue(at, to, minor, unsignedInt, offset); | ||
| } | ||
| } | ||
| case majorUtf8String: | ||
| return decodeUtf8String(at, to); | ||
| case majorMap: | ||
| return decodeMap(at, to); | ||
| case majorList: | ||
| return decodeList(at, to); | ||
| case majorUnstructuredByteString: | ||
| if (minor === minorIndefinite) { | ||
| switch (major) { | ||
| case majorUtf8String: | ||
| return decodeUtf8StringIndefinite(at, to); | ||
| case majorMap: | ||
| return decodeMapIndefinite(at, to); | ||
| case majorList: | ||
| return decodeListIndefinite(at, to); | ||
| case majorUnstructuredByteString: | ||
| return decodeUnstructuredByteStringIndefinite(at, to); | ||
| } | ||
| } | ||
| else { | ||
| switch (major) { | ||
| case majorUtf8String: | ||
| return decodeUtf8String(at, to); | ||
| case majorMap: | ||
| return decodeMap(at, to); | ||
| case majorList: | ||
| return decodeList(at, to); | ||
| case majorUnstructuredByteString: | ||
| return decodeUnstructuredByteString(at, to); | ||
| } | ||
| } | ||
| return decodeUnstructuredByteString(at, to); | ||
| default: | ||
@@ -179,24 +139,18 @@ return decodeSpecial(at, to); | ||
| } | ||
| function bytesToUtf8(bytes, at, to) { | ||
| if (USE_BUFFER$1 && bytes.constructor?.name === "Buffer") { | ||
| return bytes.toString("utf-8", at, to); | ||
| function decodeIndefinite(at, to) { | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (minor === minorIndefinite) { | ||
| switch (major) { | ||
| case majorUtf8String: | ||
| return decodeUtf8StringIndefinite(at, to); | ||
| case majorMap: | ||
| return decodeMapIndefinite(at, to); | ||
| case majorList: | ||
| return decodeListIndefinite(at, to); | ||
| case majorUnstructuredByteString: | ||
| return decodeUnstructuredByteStringIndefinite(at, to); | ||
| } | ||
| } | ||
| if (textDecoder) { | ||
| return textDecoder.decode(bytes.subarray(at, to)); | ||
| } | ||
| return toUtf8(bytes.subarray(at, to)); | ||
| } | ||
| function demote(bigInteger) { | ||
| const num = Number(bigInteger); | ||
| if (num < Number.MIN_SAFE_INTEGER || Number.MAX_SAFE_INTEGER < num) { | ||
| console.warn(new Error(`@smithy/core/cbor - truncating BigInt(${bigInteger}) to ${num} with loss of precision.`)); | ||
| } | ||
| return num; | ||
| } | ||
| const minorValueToArgumentLength = { | ||
| [extendedOneByte]: 1, | ||
| [extendedFloat16]: 2, | ||
| [extendedFloat32]: 4, | ||
| [extendedFloat64]: 8, | ||
| }; | ||
| function bytesToFloat16(a, b) { | ||
@@ -207,133 +161,58 @@ const sign = a >> 7; | ||
| const scalar = sign === 0 ? 1 : -1; | ||
| let exponentComponent; | ||
| let summation; | ||
| if (exponent === 0b00000) { | ||
| if (fraction === 0b00000_00000) { | ||
| if (fraction === 0) { | ||
| return 0; | ||
| } | ||
| else { | ||
| exponentComponent = Math.pow(2, 1 - 15); | ||
| summation = 0; | ||
| } | ||
| return scalar * (Math.pow(2, 1 - 15) * (fraction / 1024)); | ||
| } | ||
| else if (exponent === 0b11111) { | ||
| if (fraction === 0b00000_00000) { | ||
| if (fraction === 0) { | ||
| return scalar * Infinity; | ||
| } | ||
| else { | ||
| return NaN; | ||
| } | ||
| return NaN; | ||
| } | ||
| else { | ||
| exponentComponent = Math.pow(2, exponent - 15); | ||
| summation = 1; | ||
| } | ||
| summation += fraction / 1024; | ||
| return scalar * (exponentComponent * summation); | ||
| return scalar * (Math.pow(2, exponent - 15) * (1 + fraction / 1024)); | ||
| } | ||
| function decodeCount(at, to) { | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (minor < 24) { | ||
| _offset = 1; | ||
| return minor; | ||
| function decodeMap(at, to) { | ||
| const mapDataLength = decodeCount(at, to); | ||
| if (mapDataLength < 15) { | ||
| return decodeMapSmall(at, to, mapDataLength); | ||
| } | ||
| if (minor === extendedOneByte || | ||
| minor === extendedFloat16 || | ||
| minor === extendedFloat32 || | ||
| minor === extendedFloat64) { | ||
| const countLength = minorValueToArgumentLength[minor]; | ||
| _offset = (countLength + 1); | ||
| if (to - at < _offset) { | ||
| throw new Error(`countLength ${countLength} greater than remaining buf len.`); | ||
| } | ||
| const countIndex = at + 1; | ||
| if (countLength === 1) { | ||
| return payload[countIndex]; | ||
| } | ||
| else if (countLength === 2) { | ||
| return dataView$1.getUint16(countIndex); | ||
| } | ||
| else if (countLength === 4) { | ||
| return dataView$1.getUint32(countIndex); | ||
| } | ||
| return demote(dataView$1.getBigUint64(countIndex)); | ||
| } | ||
| throw new Error(`unexpected minor value ${minor}.`); | ||
| return decodeMapLarge(at, to, mapDataLength); | ||
| } | ||
| function decodeUtf8String(at, to) { | ||
| const length = decodeCount(at, to); | ||
| function decodeMapLarge(at, to, mapDataLength) { | ||
| const offset = _offset; | ||
| at += offset; | ||
| if (to - at < length) { | ||
| throw new Error(`string len ${length} greater than remaining buf len.`); | ||
| } | ||
| const value = bytesToUtf8(payload, at, at + length); | ||
| _offset = offset + length; | ||
| return value; | ||
| } | ||
| function decodeUtf8StringIndefinite(at, to) { | ||
| at += 1; | ||
| const vector = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| const data = alloc(vector.length); | ||
| data.set(vector, 0); | ||
| _offset = at - base + 2; | ||
| return bytesToUtf8(data, 0, data.length); | ||
| const base = at; | ||
| const map = Object.create(null); | ||
| for (let i = 0; i < mapDataLength; ++i) { | ||
| const key = decodeUtf8String(at, to); | ||
| at += _offset; | ||
| const valMajor = (payload[at] & 0b1110_0000) >> 5; | ||
| if (valMajor === majorUtf8String) { | ||
| map[key] = decodeUtf8String(at, to); | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (major !== majorUtf8String) { | ||
| throw new Error(`unexpected major type ${major} in indefinite string.`); | ||
| else { | ||
| map[key] = decode(at, to); | ||
| } | ||
| if (minor === minorIndefinite) { | ||
| throw new Error("nested indefinite string."); | ||
| } | ||
| const bytes = decodeUnstructuredByteString(at, to); | ||
| const length = _offset; | ||
| at += length; | ||
| for (let i = 0; i < bytes.length; ++i) { | ||
| vector.push(bytes[i]); | ||
| } | ||
| at += _offset; | ||
| } | ||
| throw new Error("expected break marker."); | ||
| _offset = offset + (at - base); | ||
| Object.setPrototypeOf(map, Object.prototype); | ||
| return map; | ||
| } | ||
| function decodeUnstructuredByteString(at, to) { | ||
| const length = decodeCount(at, to); | ||
| function decodeMapSmall(at, to, mapDataLength) { | ||
| const offset = _offset; | ||
| at += offset; | ||
| if (to - at < length) { | ||
| throw new Error(`unstructured byte string len ${length} greater than remaining buf len.`); | ||
| const base = at; | ||
| const map = {}; | ||
| for (let i = 0; i < mapDataLength; ++i) { | ||
| const key = decodeUtf8String(at, to); | ||
| at += _offset; | ||
| map[key] = decode(at, to); | ||
| at += _offset; | ||
| } | ||
| const value = payload.subarray(at, at + length); | ||
| _offset = offset + length; | ||
| return value; | ||
| _offset = offset + (at - base); | ||
| return map; | ||
| } | ||
| function decodeUnstructuredByteStringIndefinite(at, to) { | ||
| at += 1; | ||
| const vector = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| const data = alloc(vector.length); | ||
| data.set(vector, 0); | ||
| _offset = at - base + 2; | ||
| return data; | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (major !== majorUnstructuredByteString) { | ||
| throw new Error(`unexpected major type ${major} in indefinite string.`); | ||
| } | ||
| if (minor === minorIndefinite) { | ||
| throw new Error("nested indefinite string."); | ||
| } | ||
| const bytes = decodeUnstructuredByteString(at, to); | ||
| const length = _offset; | ||
| at += length; | ||
| for (let i = 0; i < bytes.length; ++i) { | ||
| vector.push(bytes[i]); | ||
| } | ||
| } | ||
| throw new Error("expected break marker."); | ||
| } | ||
| function decodeList(at, to) { | ||
@@ -346,6 +225,4 @@ const listDataLength = decodeCount(at, to); | ||
| for (let i = 0; i < listDataLength; ++i) { | ||
| const item = decode(at, to); | ||
| const itemOffset = _offset; | ||
| list[i] = item; | ||
| at += itemOffset; | ||
| list[i] = decode(at, to); | ||
| at += _offset; | ||
| } | ||
@@ -355,63 +232,105 @@ _offset = offset + (at - base); | ||
| } | ||
| function decodeListIndefinite(at, to) { | ||
| at += 1; | ||
| const list = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| _offset = at - base + 2; | ||
| return list; | ||
| function decodeUtf8String(at, to) { | ||
| const length = decodeCount(at, to); | ||
| const offset = _offset; | ||
| at += offset; | ||
| if (to - at < length) { | ||
| overflow(length); | ||
| } | ||
| _offset = offset + length; | ||
| if (length < 24) { | ||
| return decodeUtf8StringCached(at, length); | ||
| } | ||
| if (isBuffer) { | ||
| return payload.toString("utf-8", at, at + length); | ||
| } | ||
| return textDecoder.decode(payload.subarray(at, at + length)); | ||
| } | ||
| const stringCache = new Array(2048); | ||
| const stringCacheEpochs = new Uint16Array(2048); | ||
| let cacheEpoch = 0; | ||
| function advanceDecodingEpoch() { | ||
| cacheEpoch = (cacheEpoch + 1) & 0b1111_1111_1111_1111; | ||
| } | ||
| function decodeUtf8StringCached(at, length) { | ||
| let h = length; | ||
| for (let i = 0; i < length; ++i) { | ||
| h = (h * 31 + payload[at + i]) | 0; | ||
| } | ||
| const slot = (h >>> 0) & 2047; | ||
| const cached = stringCache[slot]; | ||
| if (cached !== undefined) { | ||
| if (cached.length === length) { | ||
| let match = true; | ||
| for (let i = 0; i < length; ++i) { | ||
| if (cached.charCodeAt(i) !== payload[at + i]) { | ||
| match = false; | ||
| break; | ||
| } | ||
| } | ||
| if (match) { | ||
| stringCacheEpochs[slot] = cacheEpoch; | ||
| return cached; | ||
| } | ||
| } | ||
| const item = decode(at, to); | ||
| const n = _offset; | ||
| at += n; | ||
| list.push(item); | ||
| } | ||
| throw new Error("expected break marker."); | ||
| const result = isBuffer | ||
| ? payload.toString("utf-8", at, at + length) | ||
| : textDecoder.decode(payload.subarray(at, at + length)); | ||
| if (stringCacheEpochs[slot] !== cacheEpoch) { | ||
| stringCache[slot] = result; | ||
| stringCacheEpochs[slot] = cacheEpoch; | ||
| } | ||
| return result; | ||
| } | ||
| function decodeMap(at, to) { | ||
| const mapDataLength = decodeCount(at, to); | ||
| function decodeUnstructuredByteString(at, to) { | ||
| const length = decodeCount(at, to); | ||
| const offset = _offset; | ||
| at += offset; | ||
| const base = at; | ||
| const map = {}; | ||
| for (let i = 0; i < mapDataLength; ++i) { | ||
| if (at >= to) { | ||
| throw new Error("unexpected end of map payload."); | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| if (major !== majorUtf8String) { | ||
| throw new Error(`unexpected major type ${major} for map key at index ${at}.`); | ||
| } | ||
| const key = decode(at, to); | ||
| at += _offset; | ||
| const value = decode(at, to); | ||
| at += _offset; | ||
| map[key] = value; | ||
| if (to - at < length) { | ||
| overflow(length); | ||
| } | ||
| _offset = offset + (at - base); | ||
| return map; | ||
| const value = payload.subarray(at, at + length); | ||
| _offset = offset + length; | ||
| return value; | ||
| } | ||
| function decodeMapIndefinite(at, to) { | ||
| at += 1; | ||
| const base = at; | ||
| const map = {}; | ||
| for (; at < to;) { | ||
| if (at >= to) { | ||
| throw new Error("unexpected end of map payload."); | ||
| function decodeTagValue(at, to, minor, unsignedInt, offset) { | ||
| if (minor === 2 || minor === 3) { | ||
| const length = decodeCount(at + offset, to); | ||
| let b = BigInt(0); | ||
| const start = at + offset + _offset; | ||
| for (let i = start; i < start + length; ++i) { | ||
| b = (b << BigInt(8)) | BigInt(payload[i]); | ||
| } | ||
| if (payload[at] === 0b1111_1111) { | ||
| _offset = at - base + 2; | ||
| return map; | ||
| _offset = offset + _offset + length; | ||
| return minor === 3 ? -b - BigInt(1) : b; | ||
| } | ||
| else if (minor === 4) { | ||
| const decimalFraction = decode(at + offset, to); | ||
| const [exponent, mantissa] = decimalFraction; | ||
| const normalizer = mantissa < 0 ? -1 : 1; | ||
| const mantissaStr = "0".repeat(Math.abs(exponent) + 1) + String(BigInt(normalizer) * BigInt(mantissa)); | ||
| let numericString; | ||
| const sign = mantissa < 0 ? "-" : ""; | ||
| numericString = | ||
| exponent === 0 | ||
| ? mantissaStr | ||
| : mantissaStr.slice(0, mantissaStr.length + exponent) + "." + mantissaStr.slice(exponent); | ||
| numericString = numericString.replace(/^0+/g, ""); | ||
| if (numericString === "") { | ||
| numericString = "0"; | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| if (major !== majorUtf8String) { | ||
| throw new Error(`unexpected major type ${major} for map key.`); | ||
| if (numericString[0] === ".") { | ||
| numericString = "0" + numericString; | ||
| } | ||
| const key = decode(at, to); | ||
| at += _offset; | ||
| const value = decode(at, to); | ||
| at += _offset; | ||
| map[key] = value; | ||
| numericString = sign + numericString; | ||
| _offset = offset + _offset; | ||
| return nv(numericString); | ||
| } | ||
| throw new Error("expected break marker."); | ||
| else { | ||
| const value = decode(at + offset, to); | ||
| const valueOffset = _offset; | ||
| _offset = offset + valueOffset; | ||
| return tag({ tag: castBigInt(unsignedInt), value }); | ||
| } | ||
| } | ||
@@ -450,5 +369,126 @@ function decodeSpecial(at, to) { | ||
| default: | ||
| throw new Error(`unexpected minor value ${minor}.`); | ||
| unexpectedMinor(minor); | ||
| } | ||
| } | ||
| function decodeCount(at, to) { | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (minor < 24) { | ||
| _offset = 1; | ||
| return minor; | ||
| } | ||
| switch (minor) { | ||
| case extendedOneByte: | ||
| if (to - at < 2) { | ||
| overflow(1); | ||
| } | ||
| _offset = 2; | ||
| return payload[at + 1]; | ||
| case extendedFloat16: | ||
| if (to - at < 3) { | ||
| overflow(2); | ||
| } | ||
| _offset = 3; | ||
| return dataView$1.getUint16(at + 1); | ||
| case extendedFloat32: | ||
| if (to - at < 5) { | ||
| overflow(4); | ||
| } | ||
| _offset = 5; | ||
| return dataView$1.getUint32(at + 1); | ||
| case extendedFloat64: | ||
| if (to - at < 9) { | ||
| overflow(8); | ||
| } | ||
| _offset = 9; | ||
| return demote(dataView$1.getBigUint64(at + 1)); | ||
| default: | ||
| unexpectedMinor(minor); | ||
| } | ||
| } | ||
| function decodeMapIndefinite(at, to) { | ||
| at += 1; | ||
| const base = at; | ||
| const map = {}; | ||
| for (; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| _offset = at - base + 2; | ||
| return map; | ||
| } | ||
| const key = decodeUtf8String(at, to); | ||
| at += _offset; | ||
| map[key] = decode(at, to); | ||
| at += _offset; | ||
| } | ||
| throw new Error("expected break marker."); | ||
| } | ||
| function decodeListIndefinite(at, to) { | ||
| at += 1; | ||
| const list = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| _offset = at - base + 2; | ||
| return list; | ||
| } | ||
| list.push(decode(at, to)); | ||
| at += _offset; | ||
| } | ||
| throw new Error("expected break marker."); | ||
| } | ||
| function decodeUtf8StringIndefinite(at, to) { | ||
| at += 1; | ||
| const vector = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| const data = alloc(vector.length); | ||
| data.set(vector, 0); | ||
| _offset = at - base + 2; | ||
| if (USE_BUFFER$1) { | ||
| return data.toString("utf-8", 0, data.length); | ||
| } | ||
| return textDecoder.decode(data); | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (major !== majorUtf8String) { | ||
| unexpectedMajorInIndefiniteString(major); | ||
| } | ||
| if (minor === minorIndefinite) { | ||
| throw new Error("nested indefinite string."); | ||
| } | ||
| const bytes = decodeUnstructuredByteString(at, to); | ||
| const length = _offset; | ||
| at += length; | ||
| for (let i = 0; i < bytes.length; ++i) { | ||
| vector.push(bytes[i]); | ||
| } | ||
| } | ||
| throw new Error("expected break marker."); | ||
| } | ||
| function decodeUnstructuredByteStringIndefinite(at, to) { | ||
| at += 1; | ||
| const vector = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| const data = alloc(vector.length); | ||
| data.set(vector, 0); | ||
| _offset = at - base + 2; | ||
| return data; | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (major !== majorUnstructuredByteString) { | ||
| unexpectedMajorInIndefiniteString(major); | ||
| } | ||
| if (minor === minorIndefinite) { | ||
| throw new Error("nested indefinite string."); | ||
| } | ||
| const bytes = decodeUnstructuredByteString(at, to); | ||
| const length = _offset; | ||
| at += length; | ||
| for (let i = 0; i < bytes.length; ++i) { | ||
| vector.push(bytes[i]); | ||
| } | ||
| } | ||
| throw new Error("expected break marker."); | ||
| } | ||
| function castBigInt(bigInt) { | ||
@@ -464,4 +504,23 @@ if (typeof bigInt === "number") { | ||
| } | ||
| function demote(bigInteger) { | ||
| const num = Number(bigInteger); | ||
| if (num < Number.MIN_SAFE_INTEGER || Number.MAX_SAFE_INTEGER < num) { | ||
| console.warn(new Error(`@smithy/core/cbor - truncating BigInt(${bigInteger}) to ${num} with loss of precision.`)); | ||
| } | ||
| return num; | ||
| } | ||
| function overflow(n) { | ||
| throw new Error(`length ${n} greater than remaining buf len.`); | ||
| } | ||
| function unexpectedMinor(minor) { | ||
| throw new Error(`unexpected minor value ${minor}.`); | ||
| } | ||
| function unexpectedMajorInIndefiniteString(major) { | ||
| throw new Error(`unexpected major type ${major} in indefinite string.`); | ||
| } | ||
| const USE_BUFFER = typeof Buffer !== "undefined"; | ||
| const encodeStringCache = new Map(); | ||
| let encodeCacheEpoch = 0; | ||
| let encodeCacheSaturated = false; | ||
| const initialSize = 2048; | ||
@@ -471,56 +530,2 @@ let data = alloc(initialSize); | ||
| let cursor = 0; | ||
| function ensureSpace(bytes) { | ||
| const remaining = data.byteLength - cursor; | ||
| if (remaining < bytes) { | ||
| if (cursor < 16_000_000) { | ||
| resize(Math.max(data.byteLength * 4, data.byteLength + bytes)); | ||
| } | ||
| else { | ||
| resize(data.byteLength + bytes + 16_000_000); | ||
| } | ||
| } | ||
| } | ||
| function toUint8Array() { | ||
| const out = alloc(cursor); | ||
| out.set(data.subarray(0, cursor), 0); | ||
| cursor = 0; | ||
| return out; | ||
| } | ||
| function resize(size) { | ||
| const old = data; | ||
| data = alloc(size); | ||
| if (old) { | ||
| if (old.copy) { | ||
| old.copy(data, 0, 0, old.byteLength); | ||
| } | ||
| else { | ||
| data.set(old, 0); | ||
| } | ||
| } | ||
| dataView = new DataView(data.buffer, data.byteOffset, data.byteLength); | ||
| } | ||
| function encodeHeader(major, value) { | ||
| if (value < 24) { | ||
| data[cursor++] = (major << 5) | value; | ||
| } | ||
| else if (value < 1 << 8) { | ||
| data[cursor++] = (major << 5) | 24; | ||
| data[cursor++] = value; | ||
| } | ||
| else if (value < 1 << 16) { | ||
| data[cursor++] = (major << 5) | extendedFloat16; | ||
| dataView.setUint16(cursor, value); | ||
| cursor += 2; | ||
| } | ||
| else if (value < 2 ** 32) { | ||
| data[cursor++] = (major << 5) | extendedFloat32; | ||
| dataView.setUint32(cursor, value); | ||
| cursor += 4; | ||
| } | ||
| else { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| dataView.setBigUint64(cursor, typeof value === "bigint" ? value : BigInt(value)); | ||
| cursor += 8; | ||
| } | ||
| } | ||
| function encode(_input) { | ||
@@ -530,17 +535,49 @@ const encodeStack = [_input]; | ||
| const input = encodeStack.pop(); | ||
| ensureSpace(typeof input === "string" ? input.length * 4 : 64); | ||
| if (typeof input === "string") { | ||
| const len = input.length; | ||
| if (USE_BUFFER) { | ||
| encodeHeader(majorUtf8String, Buffer.byteLength(input)); | ||
| cursor += data.write(input, cursor); | ||
| ensureSpace(len * 3 + 9); | ||
| if (len > 23) { | ||
| encodeHeader(majorUtf8String, Buffer.byteLength(input)); | ||
| cursor += data.write(input, cursor); | ||
| } | ||
| else { | ||
| encodeStringCached(input); | ||
| } | ||
| } | ||
| else { | ||
| const bytes = fromUtf8(input); | ||
| encodeHeader(majorUtf8String, bytes.byteLength); | ||
| data.set(bytes, cursor); | ||
| cursor += bytes.byteLength; | ||
| const maxBytes = len * 3; | ||
| ensureSpace(maxBytes + 9); | ||
| const headerPos = cursor; | ||
| const result = new TextEncoder().encodeInto(input, data.subarray(cursor + 9)); | ||
| const byteLen = result.written; | ||
| let headerSize; | ||
| if (byteLen < 24) { | ||
| headerSize = 1; | ||
| } | ||
| else if (byteLen < 256) { | ||
| headerSize = 2; | ||
| } | ||
| else if (byteLen < 65536) { | ||
| headerSize = 3; | ||
| } | ||
| else if (byteLen < 4294967296) { | ||
| headerSize = 5; | ||
| } | ||
| else { | ||
| headerSize = 9; | ||
| } | ||
| if (headerSize < 9) { | ||
| data.copyWithin(headerPos + headerSize, headerPos + 9, headerPos + 9 + byteLen); | ||
| } | ||
| cursor = headerPos; | ||
| encodeInteger(majorUtf8String, byteLen); | ||
| cursor += byteLen; | ||
| } | ||
| continue; | ||
| } | ||
| else if (typeof input === "number") { | ||
| if (data.byteLength - cursor < 9) { | ||
| ensureSpace(64); | ||
| } | ||
| if (typeof input === "number") { | ||
| if (Number.isInteger(input)) { | ||
@@ -560,3 +597,3 @@ const nonNegative = input >= 0; | ||
| data[cursor++] = value >> 8; | ||
| data[cursor++] = value; | ||
| data[cursor++] = value & 0xff; | ||
| } | ||
@@ -570,3 +607,6 @@ else if (value < 4294967296) { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| dataView.setBigUint64(cursor, BigInt(value)); | ||
| const hi = (value / 4294967296) | 0; | ||
| const lo = (value - hi * 4294967296) | 0; | ||
| dataView.setUint32(cursor, hi); | ||
| dataView.setUint32(cursor + 4, lo); | ||
| cursor += 8; | ||
@@ -585,25 +625,13 @@ } | ||
| const value = nonNegative ? input : -input - BigInt(1); | ||
| const n = Number(value); | ||
| if (n < 24) { | ||
| data[cursor++] = (major << 5) | n; | ||
| if (value < BigInt("18446744073709551616")) { | ||
| const n = Number(value); | ||
| if (n < 4294967296) { | ||
| encodeInteger(major, n); | ||
| } | ||
| else { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| dataView.setBigUint64(cursor, value); | ||
| cursor += 8; | ||
| } | ||
| } | ||
| else if (n < 256) { | ||
| data[cursor++] = (major << 5) | 24; | ||
| data[cursor++] = n; | ||
| } | ||
| else if (n < 65536) { | ||
| data[cursor++] = (major << 5) | extendedFloat16; | ||
| data[cursor++] = n >> 8; | ||
| data[cursor++] = n & 0b1111_1111; | ||
| } | ||
| else if (n < 4294967296) { | ||
| data[cursor++] = (major << 5) | extendedFloat32; | ||
| dataView.setUint32(cursor, n); | ||
| cursor += 4; | ||
| } | ||
| else if (value < BigInt("18446744073709551616")) { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| dataView.setBigUint64(cursor, value); | ||
| cursor += 8; | ||
| } | ||
| else { | ||
@@ -618,10 +646,5 @@ const binaryBigInt = value.toString(2); | ||
| } | ||
| ensureSpace(bigIntBytes.byteLength * 2); | ||
| ensureSpace(bigIntBytes.byteLength * 2 + 16); | ||
| data[cursor++] = nonNegative ? 0b110_00010 : 0b110_00011; | ||
| if (USE_BUFFER) { | ||
| encodeHeader(majorUnstructuredByteString, Buffer.byteLength(bigIntBytes)); | ||
| } | ||
| else { | ||
| encodeHeader(majorUnstructuredByteString, bigIntBytes.byteLength); | ||
| } | ||
| encodeHeader(majorUnstructuredByteString, bigIntBytes.byteLength); | ||
| data.set(bigIntBytes, cursor); | ||
@@ -644,11 +667,12 @@ cursor += bigIntBytes.byteLength; | ||
| else if (Array.isArray(input)) { | ||
| encodeInteger(majorList, input.length); | ||
| ensureSpace(input.length * 9 + 64); | ||
| for (let i = input.length - 1; i >= 0; --i) { | ||
| encodeStack.push(input[i]); | ||
| } | ||
| encodeHeader(majorList, input.length); | ||
| continue; | ||
| } | ||
| else if (typeof input.byteLength === "number") { | ||
| ensureSpace(input.length * 2); | ||
| encodeHeader(majorUnstructuredByteString, input.length); | ||
| ensureSpace(input.length * 2 + 9); | ||
| encodeInteger(majorUnstructuredByteString, input.length); | ||
| data.set(input, cursor); | ||
@@ -664,5 +688,5 @@ cursor += input.byteLength; | ||
| data[cursor++] = 0b110_00100; | ||
| encodeInteger(majorList, 2); | ||
| encodeStack.push(mantissa); | ||
| encodeStack.push(exponent); | ||
| encodeHeader(majorList, 2); | ||
| continue; | ||
@@ -681,8 +705,8 @@ } | ||
| const keys = Object.keys(input); | ||
| for (let i = keys.length - 1; i >= 0; --i) { | ||
| const key = keys[i]; | ||
| encodeStack.push(input[key]); | ||
| encodeStack.push(key); | ||
| const len = keys.length; | ||
| encodeInteger(majorMap, len); | ||
| for (let i = len - 1; i >= 0; --i) { | ||
| encodeStack.push(input[keys[i]]); | ||
| encodeStack.push(keys[i]); | ||
| } | ||
| encodeHeader(majorMap, keys.length); | ||
| continue; | ||
@@ -693,5 +717,127 @@ } | ||
| } | ||
| function advanceEncodingEpoch() { | ||
| encodeCacheEpoch = (encodeCacheEpoch + 1) & 0b1111_1111_1111_1111; | ||
| encodeCacheSaturated = false; | ||
| } | ||
| function toUint8Array() { | ||
| const out = alloc(cursor); | ||
| out.set(data.subarray(0, cursor), 0); | ||
| cursor = 0; | ||
| return out; | ||
| } | ||
| function resize(size) { | ||
| const old = data; | ||
| data = alloc(size); | ||
| if (old) { | ||
| if (old.copy) { | ||
| old.copy(data, 0, 0, old.byteLength); | ||
| } | ||
| else { | ||
| data.set(old, 0); | ||
| } | ||
| } | ||
| dataView = new DataView(data.buffer, data.byteOffset, data.byteLength); | ||
| } | ||
| function encodeStringCached(input) { | ||
| const cached = encodeStringCache.get(input); | ||
| if (cached !== undefined) { | ||
| data.set(cached.bytes, cursor); | ||
| cursor += cached.bytes.length; | ||
| cached.epoch = encodeCacheEpoch; | ||
| return; | ||
| } | ||
| const start = cursor; | ||
| const byteLen = Buffer.byteLength(input); | ||
| encodeInteger(majorUtf8String, byteLen); | ||
| cursor += data.write(input, cursor); | ||
| const bytes = Uint8Array.prototype.slice.call(data, start, cursor); | ||
| if (encodeStringCache.size >= 2048) { | ||
| if (encodeCacheSaturated) { | ||
| return; | ||
| } | ||
| let evicted = 0; | ||
| for (const [key, entry] of encodeStringCache) { | ||
| if (evicted >= 1024) { | ||
| break; | ||
| } | ||
| if (entry.epoch !== encodeCacheEpoch) { | ||
| encodeStringCache.delete(key); | ||
| evicted++; | ||
| } | ||
| } | ||
| if (evicted === 0) { | ||
| encodeCacheSaturated = true; | ||
| return; | ||
| } | ||
| } | ||
| if (encodeStringCache.size < 2048) { | ||
| encodeStringCache.set(input, { epoch: encodeCacheEpoch, bytes }); | ||
| } | ||
| } | ||
| function ensureSpace(bytes) { | ||
| const remaining = data.byteLength - cursor; | ||
| if (remaining < bytes) { | ||
| if (cursor < 16_000_000) { | ||
| resize(Math.max(data.byteLength * 4, data.byteLength + bytes)); | ||
| } | ||
| else { | ||
| resize(data.byteLength + bytes + 16_000_000); | ||
| } | ||
| } | ||
| } | ||
| function encodeHeader(major, value) { | ||
| if (value < 24) { | ||
| data[cursor++] = (major << 5) | value; | ||
| } | ||
| else if (value < 256) { | ||
| data[cursor++] = (major << 5) | 24; | ||
| data[cursor++] = value; | ||
| } | ||
| else if (value < 65536) { | ||
| data[cursor++] = (major << 5) | extendedFloat16; | ||
| dataView.setUint16(cursor, value); | ||
| cursor += 2; | ||
| } | ||
| else if (value < 4294967296) { | ||
| data[cursor++] = (major << 5) | extendedFloat32; | ||
| dataView.setUint32(cursor, value); | ||
| cursor += 4; | ||
| } | ||
| else { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| dataView.setBigUint64(cursor, typeof value === "bigint" ? value : BigInt(value)); | ||
| cursor += 8; | ||
| } | ||
| } | ||
| function encodeInteger(major, value) { | ||
| if (value < 24) { | ||
| data[cursor++] = (major << 5) | value; | ||
| } | ||
| else if (value < 256) { | ||
| data[cursor++] = (major << 5) | 24; | ||
| data[cursor++] = value; | ||
| } | ||
| else if (value < 65536) { | ||
| data[cursor++] = (major << 5) | extendedFloat16; | ||
| data[cursor++] = value >> 8; | ||
| data[cursor++] = value & 0xff; | ||
| } | ||
| else if (value < 4294967296) { | ||
| data[cursor++] = (major << 5) | extendedFloat32; | ||
| dataView.setUint32(cursor, value); | ||
| cursor += 4; | ||
| } | ||
| else { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| const hi = (value / 4294967296) | 0; | ||
| const lo = (value - hi * 4294967296) | 0; | ||
| dataView.setUint32(cursor, hi); | ||
| dataView.setUint32(cursor + 4, lo); | ||
| cursor += 8; | ||
| } | ||
| } | ||
| const cbor = { | ||
| deserialize(payload) { | ||
| advanceDecodingEpoch(); | ||
| setPayload(payload); | ||
@@ -701,2 +847,3 @@ return decode(0, payload.length); | ||
| serialize(input) { | ||
| advanceEncodingEpoch(); | ||
| try { | ||
@@ -703,0 +850,0 @@ encode(input); |
@@ -943,3 +943,3 @@ const { getSmithyContext, normalizeProvider } = require("@smithy/core/transport"); | ||
| for (const key in obj) { | ||
| if (obj.hasOwnProperty(key) && obj[key][textNodeName] !== undefined) { | ||
| if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key][textNodeName] !== undefined) { | ||
| obj[key] = obj[key][textNodeName]; | ||
@@ -946,0 +946,0 @@ } |
@@ -1,11 +0,12 @@ | ||
| import { nv, toUtf8 } from "@smithy/core/serde"; | ||
| import { nv } from "@smithy/core/serde"; | ||
| import { alloc, extendedFloat16, extendedFloat32, extendedFloat64, extendedOneByte, majorList, majorMap, majorNegativeInt64, majorTag, majorUint64, majorUnstructuredByteString, majorUtf8String, minorIndefinite, specialFalse, specialNull, specialTrue, specialUndefined, tag, } from "./cbor-types"; | ||
| const USE_TEXT_DECODER = typeof TextDecoder !== "undefined"; | ||
| const USE_BUFFER = typeof Buffer !== "undefined"; | ||
| const textDecoder = new TextDecoder(); | ||
| let payload = alloc(0); | ||
| let isBuffer = false; | ||
| let dataView = new DataView(payload.buffer, payload.byteOffset, payload.byteLength); | ||
| const textDecoder = USE_TEXT_DECODER ? new TextDecoder() : null; | ||
| let _offset = 0; | ||
| export function setPayload(bytes) { | ||
| payload = bytes; | ||
| isBuffer = USE_BUFFER && payload instanceof Buffer; | ||
| dataView = new DataView(payload.buffer, payload.byteOffset, payload.byteLength); | ||
@@ -19,6 +20,9 @@ } | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (minor === minorIndefinite && 2 <= major && major <= 5) { | ||
| return decodeIndefinite(at, to); | ||
| } | ||
| switch (major) { | ||
| case majorUint64: | ||
| case majorNegativeInt64: | ||
| case majorTag: | ||
| case majorTag: { | ||
| let unsignedInt; | ||
@@ -33,27 +37,39 @@ let offset; | ||
| case extendedOneByte: | ||
| if (to - at < 2) { | ||
| overflow(1); | ||
| } | ||
| unsignedInt = payload[at + 1]; | ||
| offset = 2; | ||
| break; | ||
| case extendedFloat16: | ||
| if (to - at < 3) { | ||
| overflow(2); | ||
| } | ||
| unsignedInt = dataView.getUint16(at + 1); | ||
| offset = 3; | ||
| break; | ||
| case extendedFloat32: | ||
| if (to - at < 5) { | ||
| overflow(4); | ||
| } | ||
| unsignedInt = dataView.getUint32(at + 1); | ||
| offset = 5; | ||
| break; | ||
| case extendedFloat64: | ||
| const countLength = minorValueToArgumentLength[minor]; | ||
| const countOffset = (countLength + 1); | ||
| offset = countOffset; | ||
| if (to - at < countOffset) { | ||
| throw new Error(`countLength ${countLength} greater than remaining buf len.`); | ||
| if (to - at < 9) { | ||
| overflow(8); | ||
| } | ||
| const countIndex = at + 1; | ||
| if (countLength === 1) { | ||
| unsignedInt = payload[countIndex]; | ||
| { | ||
| const hi = dataView.getUint32(at + 1); | ||
| if (hi < 0x00200000) { | ||
| unsignedInt = hi * 4294967296 + dataView.getUint32(at + 5); | ||
| } | ||
| else { | ||
| unsignedInt = dataView.getBigUint64(at + 1); | ||
| } | ||
| } | ||
| else if (countLength === 2) { | ||
| unsignedInt = dataView.getUint16(countIndex); | ||
| } | ||
| else if (countLength === 4) { | ||
| unsignedInt = dataView.getUint32(countIndex); | ||
| } | ||
| else { | ||
| unsignedInt = dataView.getBigUint64(countIndex); | ||
| } | ||
| offset = 9; | ||
| break; | ||
| default: | ||
| throw new Error(`unexpected minor value ${minor}.`); | ||
| unexpectedMinor(minor); | ||
| } | ||
@@ -77,69 +93,13 @@ } | ||
| else { | ||
| if (minor === 2 || minor === 3) { | ||
| const length = decodeCount(at + offset, to); | ||
| let b = BigInt(0); | ||
| const start = at + offset + _offset; | ||
| for (let i = start; i < start + length; ++i) { | ||
| b = (b << BigInt(8)) | BigInt(payload[i]); | ||
| } | ||
| _offset = offset + _offset + length; | ||
| return minor === 3 ? -b - BigInt(1) : b; | ||
| } | ||
| else if (minor === 4) { | ||
| const decimalFraction = decode(at + offset, to); | ||
| const [exponent, mantissa] = decimalFraction; | ||
| const normalizer = mantissa < 0 ? -1 : 1; | ||
| const mantissaStr = "0".repeat(Math.abs(exponent) + 1) + String(BigInt(normalizer) * BigInt(mantissa)); | ||
| let numericString; | ||
| const sign = mantissa < 0 ? "-" : ""; | ||
| numericString = | ||
| exponent === 0 | ||
| ? mantissaStr | ||
| : mantissaStr.slice(0, mantissaStr.length + exponent) + "." + mantissaStr.slice(exponent); | ||
| numericString = numericString.replace(/^0+/g, ""); | ||
| if (numericString === "") { | ||
| numericString = "0"; | ||
| } | ||
| if (numericString[0] === ".") { | ||
| numericString = "0" + numericString; | ||
| } | ||
| numericString = sign + numericString; | ||
| _offset = offset + _offset; | ||
| return nv(numericString); | ||
| } | ||
| else { | ||
| const value = decode(at + offset, to); | ||
| const valueOffset = _offset; | ||
| _offset = offset + valueOffset; | ||
| return tag({ tag: castBigInt(unsignedInt), value }); | ||
| } | ||
| return decodeTagValue(at, to, minor, unsignedInt, offset); | ||
| } | ||
| } | ||
| case majorUtf8String: | ||
| return decodeUtf8String(at, to); | ||
| case majorMap: | ||
| return decodeMap(at, to); | ||
| case majorList: | ||
| return decodeList(at, to); | ||
| case majorUnstructuredByteString: | ||
| if (minor === minorIndefinite) { | ||
| switch (major) { | ||
| case majorUtf8String: | ||
| return decodeUtf8StringIndefinite(at, to); | ||
| case majorMap: | ||
| return decodeMapIndefinite(at, to); | ||
| case majorList: | ||
| return decodeListIndefinite(at, to); | ||
| case majorUnstructuredByteString: | ||
| return decodeUnstructuredByteStringIndefinite(at, to); | ||
| } | ||
| } | ||
| else { | ||
| switch (major) { | ||
| case majorUtf8String: | ||
| return decodeUtf8String(at, to); | ||
| case majorMap: | ||
| return decodeMap(at, to); | ||
| case majorList: | ||
| return decodeList(at, to); | ||
| case majorUnstructuredByteString: | ||
| return decodeUnstructuredByteString(at, to); | ||
| } | ||
| } | ||
| return decodeUnstructuredByteString(at, to); | ||
| default: | ||
@@ -149,24 +109,19 @@ return decodeSpecial(at, to); | ||
| } | ||
| function bytesToUtf8(bytes, at, to) { | ||
| if (USE_BUFFER && bytes.constructor?.name === "Buffer") { | ||
| return bytes.toString("utf-8", at, to); | ||
| function decodeIndefinite(at, to) { | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (minor === minorIndefinite) { | ||
| switch (major) { | ||
| case majorUtf8String: | ||
| return decodeUtf8StringIndefinite(at, to); | ||
| case majorMap: | ||
| return decodeMapIndefinite(at, to); | ||
| case majorList: | ||
| return decodeListIndefinite(at, to); | ||
| case majorUnstructuredByteString: | ||
| return decodeUnstructuredByteStringIndefinite(at, to); | ||
| default: | ||
| } | ||
| } | ||
| if (textDecoder) { | ||
| return textDecoder.decode(bytes.subarray(at, to)); | ||
| } | ||
| return toUtf8(bytes.subarray(at, to)); | ||
| } | ||
| function demote(bigInteger) { | ||
| const num = Number(bigInteger); | ||
| if (num < Number.MIN_SAFE_INTEGER || Number.MAX_SAFE_INTEGER < num) { | ||
| console.warn(new Error(`@smithy/core/cbor - truncating BigInt(${bigInteger}) to ${num} with loss of precision.`)); | ||
| } | ||
| return num; | ||
| } | ||
| const minorValueToArgumentLength = { | ||
| [extendedOneByte]: 1, | ||
| [extendedFloat16]: 2, | ||
| [extendedFloat32]: 4, | ||
| [extendedFloat64]: 8, | ||
| }; | ||
| export function bytesToFloat16(a, b) { | ||
@@ -177,133 +132,58 @@ const sign = a >> 7; | ||
| const scalar = sign === 0 ? 1 : -1; | ||
| let exponentComponent; | ||
| let summation; | ||
| if (exponent === 0b00000) { | ||
| if (fraction === 0b00000_00000) { | ||
| if (fraction === 0) { | ||
| return 0; | ||
| } | ||
| else { | ||
| exponentComponent = Math.pow(2, 1 - 15); | ||
| summation = 0; | ||
| } | ||
| return scalar * (Math.pow(2, 1 - 15) * (fraction / 1024)); | ||
| } | ||
| else if (exponent === 0b11111) { | ||
| if (fraction === 0b00000_00000) { | ||
| if (fraction === 0) { | ||
| return scalar * Infinity; | ||
| } | ||
| else { | ||
| return NaN; | ||
| } | ||
| return NaN; | ||
| } | ||
| else { | ||
| exponentComponent = Math.pow(2, exponent - 15); | ||
| summation = 1; | ||
| } | ||
| summation += fraction / 1024; | ||
| return scalar * (exponentComponent * summation); | ||
| return scalar * (Math.pow(2, exponent - 15) * (1 + fraction / 1024)); | ||
| } | ||
| function decodeCount(at, to) { | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (minor < 24) { | ||
| _offset = 1; | ||
| return minor; | ||
| function decodeMap(at, to) { | ||
| const mapDataLength = decodeCount(at, to); | ||
| if (mapDataLength < 15) { | ||
| return decodeMapSmall(at, to, mapDataLength); | ||
| } | ||
| if (minor === extendedOneByte || | ||
| minor === extendedFloat16 || | ||
| minor === extendedFloat32 || | ||
| minor === extendedFloat64) { | ||
| const countLength = minorValueToArgumentLength[minor]; | ||
| _offset = (countLength + 1); | ||
| if (to - at < _offset) { | ||
| throw new Error(`countLength ${countLength} greater than remaining buf len.`); | ||
| } | ||
| const countIndex = at + 1; | ||
| if (countLength === 1) { | ||
| return payload[countIndex]; | ||
| } | ||
| else if (countLength === 2) { | ||
| return dataView.getUint16(countIndex); | ||
| } | ||
| else if (countLength === 4) { | ||
| return dataView.getUint32(countIndex); | ||
| } | ||
| return demote(dataView.getBigUint64(countIndex)); | ||
| } | ||
| throw new Error(`unexpected minor value ${minor}.`); | ||
| return decodeMapLarge(at, to, mapDataLength); | ||
| } | ||
| function decodeUtf8String(at, to) { | ||
| const length = decodeCount(at, to); | ||
| function decodeMapLarge(at, to, mapDataLength) { | ||
| const offset = _offset; | ||
| at += offset; | ||
| if (to - at < length) { | ||
| throw new Error(`string len ${length} greater than remaining buf len.`); | ||
| } | ||
| const value = bytesToUtf8(payload, at, at + length); | ||
| _offset = offset + length; | ||
| return value; | ||
| } | ||
| function decodeUtf8StringIndefinite(at, to) { | ||
| at += 1; | ||
| const vector = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| const data = alloc(vector.length); | ||
| data.set(vector, 0); | ||
| _offset = at - base + 2; | ||
| return bytesToUtf8(data, 0, data.length); | ||
| const base = at; | ||
| const map = Object.create(null); | ||
| for (let i = 0; i < mapDataLength; ++i) { | ||
| const key = decodeUtf8String(at, to); | ||
| at += _offset; | ||
| const valMajor = (payload[at] & 0b1110_0000) >> 5; | ||
| if (valMajor === majorUtf8String) { | ||
| map[key] = decodeUtf8String(at, to); | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (major !== majorUtf8String) { | ||
| throw new Error(`unexpected major type ${major} in indefinite string.`); | ||
| else { | ||
| map[key] = decode(at, to); | ||
| } | ||
| if (minor === minorIndefinite) { | ||
| throw new Error("nested indefinite string."); | ||
| } | ||
| const bytes = decodeUnstructuredByteString(at, to); | ||
| const length = _offset; | ||
| at += length; | ||
| for (let i = 0; i < bytes.length; ++i) { | ||
| vector.push(bytes[i]); | ||
| } | ||
| at += _offset; | ||
| } | ||
| throw new Error("expected break marker."); | ||
| _offset = offset + (at - base); | ||
| Object.setPrototypeOf(map, Object.prototype); | ||
| return map; | ||
| } | ||
| function decodeUnstructuredByteString(at, to) { | ||
| const length = decodeCount(at, to); | ||
| function decodeMapSmall(at, to, mapDataLength) { | ||
| const offset = _offset; | ||
| at += offset; | ||
| if (to - at < length) { | ||
| throw new Error(`unstructured byte string len ${length} greater than remaining buf len.`); | ||
| const base = at; | ||
| const map = {}; | ||
| for (let i = 0; i < mapDataLength; ++i) { | ||
| const key = decodeUtf8String(at, to); | ||
| at += _offset; | ||
| map[key] = decode(at, to); | ||
| at += _offset; | ||
| } | ||
| const value = payload.subarray(at, at + length); | ||
| _offset = offset + length; | ||
| return value; | ||
| _offset = offset + (at - base); | ||
| return map; | ||
| } | ||
| function decodeUnstructuredByteStringIndefinite(at, to) { | ||
| at += 1; | ||
| const vector = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| const data = alloc(vector.length); | ||
| data.set(vector, 0); | ||
| _offset = at - base + 2; | ||
| return data; | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (major !== majorUnstructuredByteString) { | ||
| throw new Error(`unexpected major type ${major} in indefinite string.`); | ||
| } | ||
| if (minor === minorIndefinite) { | ||
| throw new Error("nested indefinite string."); | ||
| } | ||
| const bytes = decodeUnstructuredByteString(at, to); | ||
| const length = _offset; | ||
| at += length; | ||
| for (let i = 0; i < bytes.length; ++i) { | ||
| vector.push(bytes[i]); | ||
| } | ||
| } | ||
| throw new Error("expected break marker."); | ||
| } | ||
| function decodeList(at, to) { | ||
@@ -316,6 +196,4 @@ const listDataLength = decodeCount(at, to); | ||
| for (let i = 0; i < listDataLength; ++i) { | ||
| const item = decode(at, to); | ||
| const itemOffset = _offset; | ||
| list[i] = item; | ||
| at += itemOffset; | ||
| list[i] = decode(at, to); | ||
| at += _offset; | ||
| } | ||
@@ -325,63 +203,105 @@ _offset = offset + (at - base); | ||
| } | ||
| function decodeListIndefinite(at, to) { | ||
| at += 1; | ||
| const list = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| _offset = at - base + 2; | ||
| return list; | ||
| function decodeUtf8String(at, to) { | ||
| const length = decodeCount(at, to); | ||
| const offset = _offset; | ||
| at += offset; | ||
| if (to - at < length) { | ||
| overflow(length); | ||
| } | ||
| _offset = offset + length; | ||
| if (length < 24) { | ||
| return decodeUtf8StringCached(at, length); | ||
| } | ||
| if (isBuffer) { | ||
| return payload.toString("utf-8", at, at + length); | ||
| } | ||
| return textDecoder.decode(payload.subarray(at, at + length)); | ||
| } | ||
| const stringCache = new Array(2048); | ||
| const stringCacheEpochs = new Uint16Array(2048); | ||
| let cacheEpoch = 0; | ||
| export function advanceDecodingEpoch() { | ||
| cacheEpoch = (cacheEpoch + 1) & 0b1111_1111_1111_1111; | ||
| } | ||
| function decodeUtf8StringCached(at, length) { | ||
| let h = length; | ||
| for (let i = 0; i < length; ++i) { | ||
| h = (h * 31 + payload[at + i]) | 0; | ||
| } | ||
| const slot = (h >>> 0) & 2047; | ||
| const cached = stringCache[slot]; | ||
| if (cached !== undefined) { | ||
| if (cached.length === length) { | ||
| let match = true; | ||
| for (let i = 0; i < length; ++i) { | ||
| if (cached.charCodeAt(i) !== payload[at + i]) { | ||
| match = false; | ||
| break; | ||
| } | ||
| } | ||
| if (match) { | ||
| stringCacheEpochs[slot] = cacheEpoch; | ||
| return cached; | ||
| } | ||
| } | ||
| const item = decode(at, to); | ||
| const n = _offset; | ||
| at += n; | ||
| list.push(item); | ||
| } | ||
| throw new Error("expected break marker."); | ||
| const result = isBuffer | ||
| ? payload.toString("utf-8", at, at + length) | ||
| : textDecoder.decode(payload.subarray(at, at + length)); | ||
| if (stringCacheEpochs[slot] !== cacheEpoch) { | ||
| stringCache[slot] = result; | ||
| stringCacheEpochs[slot] = cacheEpoch; | ||
| } | ||
| return result; | ||
| } | ||
| function decodeMap(at, to) { | ||
| const mapDataLength = decodeCount(at, to); | ||
| function decodeUnstructuredByteString(at, to) { | ||
| const length = decodeCount(at, to); | ||
| const offset = _offset; | ||
| at += offset; | ||
| const base = at; | ||
| const map = {}; | ||
| for (let i = 0; i < mapDataLength; ++i) { | ||
| if (at >= to) { | ||
| throw new Error("unexpected end of map payload."); | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| if (major !== majorUtf8String) { | ||
| throw new Error(`unexpected major type ${major} for map key at index ${at}.`); | ||
| } | ||
| const key = decode(at, to); | ||
| at += _offset; | ||
| const value = decode(at, to); | ||
| at += _offset; | ||
| map[key] = value; | ||
| if (to - at < length) { | ||
| overflow(length); | ||
| } | ||
| _offset = offset + (at - base); | ||
| return map; | ||
| const value = payload.subarray(at, at + length); | ||
| _offset = offset + length; | ||
| return value; | ||
| } | ||
| function decodeMapIndefinite(at, to) { | ||
| at += 1; | ||
| const base = at; | ||
| const map = {}; | ||
| for (; at < to;) { | ||
| if (at >= to) { | ||
| throw new Error("unexpected end of map payload."); | ||
| function decodeTagValue(at, to, minor, unsignedInt, offset) { | ||
| if (minor === 2 || minor === 3) { | ||
| const length = decodeCount(at + offset, to); | ||
| let b = BigInt(0); | ||
| const start = at + offset + _offset; | ||
| for (let i = start; i < start + length; ++i) { | ||
| b = (b << BigInt(8)) | BigInt(payload[i]); | ||
| } | ||
| if (payload[at] === 0b1111_1111) { | ||
| _offset = at - base + 2; | ||
| return map; | ||
| _offset = offset + _offset + length; | ||
| return minor === 3 ? -b - BigInt(1) : b; | ||
| } | ||
| else if (minor === 4) { | ||
| const decimalFraction = decode(at + offset, to); | ||
| const [exponent, mantissa] = decimalFraction; | ||
| const normalizer = mantissa < 0 ? -1 : 1; | ||
| const mantissaStr = "0".repeat(Math.abs(exponent) + 1) + String(BigInt(normalizer) * BigInt(mantissa)); | ||
| let numericString; | ||
| const sign = mantissa < 0 ? "-" : ""; | ||
| numericString = | ||
| exponent === 0 | ||
| ? mantissaStr | ||
| : mantissaStr.slice(0, mantissaStr.length + exponent) + "." + mantissaStr.slice(exponent); | ||
| numericString = numericString.replace(/^0+/g, ""); | ||
| if (numericString === "") { | ||
| numericString = "0"; | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| if (major !== majorUtf8String) { | ||
| throw new Error(`unexpected major type ${major} for map key.`); | ||
| if (numericString[0] === ".") { | ||
| numericString = "0" + numericString; | ||
| } | ||
| const key = decode(at, to); | ||
| at += _offset; | ||
| const value = decode(at, to); | ||
| at += _offset; | ||
| map[key] = value; | ||
| numericString = sign + numericString; | ||
| _offset = offset + _offset; | ||
| return nv(numericString); | ||
| } | ||
| throw new Error("expected break marker."); | ||
| else { | ||
| const value = decode(at + offset, to); | ||
| const valueOffset = _offset; | ||
| _offset = offset + valueOffset; | ||
| return tag({ tag: castBigInt(unsignedInt), value }); | ||
| } | ||
| } | ||
@@ -420,5 +340,126 @@ function decodeSpecial(at, to) { | ||
| default: | ||
| throw new Error(`unexpected minor value ${minor}.`); | ||
| unexpectedMinor(minor); | ||
| } | ||
| } | ||
| function decodeCount(at, to) { | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (minor < 24) { | ||
| _offset = 1; | ||
| return minor; | ||
| } | ||
| switch (minor) { | ||
| case extendedOneByte: | ||
| if (to - at < 2) { | ||
| overflow(1); | ||
| } | ||
| _offset = 2; | ||
| return payload[at + 1]; | ||
| case extendedFloat16: | ||
| if (to - at < 3) { | ||
| overflow(2); | ||
| } | ||
| _offset = 3; | ||
| return dataView.getUint16(at + 1); | ||
| case extendedFloat32: | ||
| if (to - at < 5) { | ||
| overflow(4); | ||
| } | ||
| _offset = 5; | ||
| return dataView.getUint32(at + 1); | ||
| case extendedFloat64: | ||
| if (to - at < 9) { | ||
| overflow(8); | ||
| } | ||
| _offset = 9; | ||
| return demote(dataView.getBigUint64(at + 1)); | ||
| default: | ||
| unexpectedMinor(minor); | ||
| } | ||
| } | ||
| function decodeMapIndefinite(at, to) { | ||
| at += 1; | ||
| const base = at; | ||
| const map = {}; | ||
| for (; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| _offset = at - base + 2; | ||
| return map; | ||
| } | ||
| const key = decodeUtf8String(at, to); | ||
| at += _offset; | ||
| map[key] = decode(at, to); | ||
| at += _offset; | ||
| } | ||
| throw new Error("expected break marker."); | ||
| } | ||
| function decodeListIndefinite(at, to) { | ||
| at += 1; | ||
| const list = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| _offset = at - base + 2; | ||
| return list; | ||
| } | ||
| list.push(decode(at, to)); | ||
| at += _offset; | ||
| } | ||
| throw new Error("expected break marker."); | ||
| } | ||
| function decodeUtf8StringIndefinite(at, to) { | ||
| at += 1; | ||
| const vector = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| const data = alloc(vector.length); | ||
| data.set(vector, 0); | ||
| _offset = at - base + 2; | ||
| if (USE_BUFFER) { | ||
| return data.toString("utf-8", 0, data.length); | ||
| } | ||
| return textDecoder.decode(data); | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (major !== majorUtf8String) { | ||
| unexpectedMajorInIndefiniteString(major); | ||
| } | ||
| if (minor === minorIndefinite) { | ||
| throw new Error("nested indefinite string."); | ||
| } | ||
| const bytes = decodeUnstructuredByteString(at, to); | ||
| const length = _offset; | ||
| at += length; | ||
| for (let i = 0; i < bytes.length; ++i) { | ||
| vector.push(bytes[i]); | ||
| } | ||
| } | ||
| throw new Error("expected break marker."); | ||
| } | ||
| function decodeUnstructuredByteStringIndefinite(at, to) { | ||
| at += 1; | ||
| const vector = []; | ||
| for (const base = at; at < to;) { | ||
| if (payload[at] === 0b1111_1111) { | ||
| const data = alloc(vector.length); | ||
| data.set(vector, 0); | ||
| _offset = at - base + 2; | ||
| return data; | ||
| } | ||
| const major = (payload[at] & 0b1110_0000) >> 5; | ||
| const minor = payload[at] & 0b0001_1111; | ||
| if (major !== majorUnstructuredByteString) { | ||
| unexpectedMajorInIndefiniteString(major); | ||
| } | ||
| if (minor === minorIndefinite) { | ||
| throw new Error("nested indefinite string."); | ||
| } | ||
| const bytes = decodeUnstructuredByteString(at, to); | ||
| const length = _offset; | ||
| at += length; | ||
| for (let i = 0; i < bytes.length; ++i) { | ||
| vector.push(bytes[i]); | ||
| } | ||
| } | ||
| throw new Error("expected break marker."); | ||
| } | ||
| function castBigInt(bigInt) { | ||
@@ -434,1 +475,17 @@ if (typeof bigInt === "number") { | ||
| } | ||
| function demote(bigInteger) { | ||
| const num = Number(bigInteger); | ||
| if (num < Number.MIN_SAFE_INTEGER || Number.MAX_SAFE_INTEGER < num) { | ||
| console.warn(new Error(`@smithy/core/cbor - truncating BigInt(${bigInteger}) to ${num} with loss of precision.`)); | ||
| } | ||
| return num; | ||
| } | ||
| function overflow(n) { | ||
| throw new Error(`length ${n} greater than remaining buf len.`); | ||
| } | ||
| function unexpectedMinor(minor) { | ||
| throw new Error(`unexpected minor value ${minor}.`); | ||
| } | ||
| function unexpectedMajorInIndefiniteString(major) { | ||
| throw new Error(`unexpected major type ${major} in indefinite string.`); | ||
| } |
@@ -1,4 +0,7 @@ | ||
| import { NumericValue, fromUtf8 } from "@smithy/core/serde"; | ||
| import { NumericValue } from "@smithy/core/serde"; | ||
| import { alloc, extendedFloat16, extendedFloat32, extendedFloat64, majorList, majorMap, majorNegativeInt64, majorSpecial, majorTag, majorUint64, majorUnstructuredByteString, majorUtf8String, specialFalse, specialNull, specialTrue, tagSymbol, } from "./cbor-types"; | ||
| const USE_BUFFER = typeof Buffer !== "undefined"; | ||
| const encodeStringCache = new Map(); | ||
| let encodeCacheEpoch = 0; | ||
| let encodeCacheSaturated = false; | ||
| const initialSize = 2048; | ||
@@ -8,56 +11,2 @@ let data = alloc(initialSize); | ||
| let cursor = 0; | ||
| function ensureSpace(bytes) { | ||
| const remaining = data.byteLength - cursor; | ||
| if (remaining < bytes) { | ||
| if (cursor < 16_000_000) { | ||
| resize(Math.max(data.byteLength * 4, data.byteLength + bytes)); | ||
| } | ||
| else { | ||
| resize(data.byteLength + bytes + 16_000_000); | ||
| } | ||
| } | ||
| } | ||
| export function toUint8Array() { | ||
| const out = alloc(cursor); | ||
| out.set(data.subarray(0, cursor), 0); | ||
| cursor = 0; | ||
| return out; | ||
| } | ||
| export function resize(size) { | ||
| const old = data; | ||
| data = alloc(size); | ||
| if (old) { | ||
| if (old.copy) { | ||
| old.copy(data, 0, 0, old.byteLength); | ||
| } | ||
| else { | ||
| data.set(old, 0); | ||
| } | ||
| } | ||
| dataView = new DataView(data.buffer, data.byteOffset, data.byteLength); | ||
| } | ||
| function encodeHeader(major, value) { | ||
| if (value < 24) { | ||
| data[cursor++] = (major << 5) | value; | ||
| } | ||
| else if (value < 1 << 8) { | ||
| data[cursor++] = (major << 5) | 24; | ||
| data[cursor++] = value; | ||
| } | ||
| else if (value < 1 << 16) { | ||
| data[cursor++] = (major << 5) | extendedFloat16; | ||
| dataView.setUint16(cursor, value); | ||
| cursor += 2; | ||
| } | ||
| else if (value < 2 ** 32) { | ||
| data[cursor++] = (major << 5) | extendedFloat32; | ||
| dataView.setUint32(cursor, value); | ||
| cursor += 4; | ||
| } | ||
| else { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| dataView.setBigUint64(cursor, typeof value === "bigint" ? value : BigInt(value)); | ||
| cursor += 8; | ||
| } | ||
| } | ||
| export function encode(_input) { | ||
@@ -67,17 +16,49 @@ const encodeStack = [_input]; | ||
| const input = encodeStack.pop(); | ||
| ensureSpace(typeof input === "string" ? input.length * 4 : 64); | ||
| if (typeof input === "string") { | ||
| const len = input.length; | ||
| if (USE_BUFFER) { | ||
| encodeHeader(majorUtf8String, Buffer.byteLength(input)); | ||
| cursor += data.write(input, cursor); | ||
| ensureSpace(len * 3 + 9); | ||
| if (len > 23) { | ||
| encodeHeader(majorUtf8String, Buffer.byteLength(input)); | ||
| cursor += data.write(input, cursor); | ||
| } | ||
| else { | ||
| encodeStringCached(input); | ||
| } | ||
| } | ||
| else { | ||
| const bytes = fromUtf8(input); | ||
| encodeHeader(majorUtf8String, bytes.byteLength); | ||
| data.set(bytes, cursor); | ||
| cursor += bytes.byteLength; | ||
| const maxBytes = len * 3; | ||
| ensureSpace(maxBytes + 9); | ||
| const headerPos = cursor; | ||
| const result = new TextEncoder().encodeInto(input, data.subarray(cursor + 9)); | ||
| const byteLen = result.written; | ||
| let headerSize; | ||
| if (byteLen < 24) { | ||
| headerSize = 1; | ||
| } | ||
| else if (byteLen < 256) { | ||
| headerSize = 2; | ||
| } | ||
| else if (byteLen < 65536) { | ||
| headerSize = 3; | ||
| } | ||
| else if (byteLen < 4294967296) { | ||
| headerSize = 5; | ||
| } | ||
| else { | ||
| headerSize = 9; | ||
| } | ||
| if (headerSize < 9) { | ||
| data.copyWithin(headerPos + headerSize, headerPos + 9, headerPos + 9 + byteLen); | ||
| } | ||
| cursor = headerPos; | ||
| encodeInteger(majorUtf8String, byteLen); | ||
| cursor += byteLen; | ||
| } | ||
| continue; | ||
| } | ||
| else if (typeof input === "number") { | ||
| if (data.byteLength - cursor < 9) { | ||
| ensureSpace(64); | ||
| } | ||
| if (typeof input === "number") { | ||
| if (Number.isInteger(input)) { | ||
@@ -97,3 +78,3 @@ const nonNegative = input >= 0; | ||
| data[cursor++] = value >> 8; | ||
| data[cursor++] = value; | ||
| data[cursor++] = value & 0xff; | ||
| } | ||
@@ -107,3 +88,6 @@ else if (value < 4294967296) { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| dataView.setBigUint64(cursor, BigInt(value)); | ||
| const hi = (value / 4294967296) | 0; | ||
| const lo = (value - hi * 4294967296) | 0; | ||
| dataView.setUint32(cursor, hi); | ||
| dataView.setUint32(cursor + 4, lo); | ||
| cursor += 8; | ||
@@ -122,25 +106,13 @@ } | ||
| const value = nonNegative ? input : -input - BigInt(1); | ||
| const n = Number(value); | ||
| if (n < 24) { | ||
| data[cursor++] = (major << 5) | n; | ||
| if (value < BigInt("18446744073709551616")) { | ||
| const n = Number(value); | ||
| if (n < 4294967296) { | ||
| encodeInteger(major, n); | ||
| } | ||
| else { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| dataView.setBigUint64(cursor, value); | ||
| cursor += 8; | ||
| } | ||
| } | ||
| else if (n < 256) { | ||
| data[cursor++] = (major << 5) | 24; | ||
| data[cursor++] = n; | ||
| } | ||
| else if (n < 65536) { | ||
| data[cursor++] = (major << 5) | extendedFloat16; | ||
| data[cursor++] = n >> 8; | ||
| data[cursor++] = n & 0b1111_1111; | ||
| } | ||
| else if (n < 4294967296) { | ||
| data[cursor++] = (major << 5) | extendedFloat32; | ||
| dataView.setUint32(cursor, n); | ||
| cursor += 4; | ||
| } | ||
| else if (value < BigInt("18446744073709551616")) { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| dataView.setBigUint64(cursor, value); | ||
| cursor += 8; | ||
| } | ||
| else { | ||
@@ -155,10 +127,5 @@ const binaryBigInt = value.toString(2); | ||
| } | ||
| ensureSpace(bigIntBytes.byteLength * 2); | ||
| ensureSpace(bigIntBytes.byteLength * 2 + 16); | ||
| data[cursor++] = nonNegative ? 0b110_00010 : 0b110_00011; | ||
| if (USE_BUFFER) { | ||
| encodeHeader(majorUnstructuredByteString, Buffer.byteLength(bigIntBytes)); | ||
| } | ||
| else { | ||
| encodeHeader(majorUnstructuredByteString, bigIntBytes.byteLength); | ||
| } | ||
| encodeHeader(majorUnstructuredByteString, bigIntBytes.byteLength); | ||
| data.set(bigIntBytes, cursor); | ||
@@ -181,11 +148,12 @@ cursor += bigIntBytes.byteLength; | ||
| else if (Array.isArray(input)) { | ||
| encodeInteger(majorList, input.length); | ||
| ensureSpace(input.length * 9 + 64); | ||
| for (let i = input.length - 1; i >= 0; --i) { | ||
| encodeStack.push(input[i]); | ||
| } | ||
| encodeHeader(majorList, input.length); | ||
| continue; | ||
| } | ||
| else if (typeof input.byteLength === "number") { | ||
| ensureSpace(input.length * 2); | ||
| encodeHeader(majorUnstructuredByteString, input.length); | ||
| ensureSpace(input.length * 2 + 9); | ||
| encodeInteger(majorUnstructuredByteString, input.length); | ||
| data.set(input, cursor); | ||
@@ -201,5 +169,5 @@ cursor += input.byteLength; | ||
| data[cursor++] = 0b110_00100; | ||
| encodeInteger(majorList, 2); | ||
| encodeStack.push(mantissa); | ||
| encodeStack.push(exponent); | ||
| encodeHeader(majorList, 2); | ||
| continue; | ||
@@ -218,8 +186,8 @@ } | ||
| const keys = Object.keys(input); | ||
| for (let i = keys.length - 1; i >= 0; --i) { | ||
| const key = keys[i]; | ||
| encodeStack.push(input[key]); | ||
| encodeStack.push(key); | ||
| const len = keys.length; | ||
| encodeInteger(majorMap, len); | ||
| for (let i = len - 1; i >= 0; --i) { | ||
| encodeStack.push(input[keys[i]]); | ||
| encodeStack.push(keys[i]); | ||
| } | ||
| encodeHeader(majorMap, keys.length); | ||
| continue; | ||
@@ -230,1 +198,122 @@ } | ||
| } | ||
| export function advanceEncodingEpoch() { | ||
| encodeCacheEpoch = (encodeCacheEpoch + 1) & 0b1111_1111_1111_1111; | ||
| encodeCacheSaturated = false; | ||
| } | ||
| export function toUint8Array() { | ||
| const out = alloc(cursor); | ||
| out.set(data.subarray(0, cursor), 0); | ||
| cursor = 0; | ||
| return out; | ||
| } | ||
| export function resize(size) { | ||
| const old = data; | ||
| data = alloc(size); | ||
| if (old) { | ||
| if (old.copy) { | ||
| old.copy(data, 0, 0, old.byteLength); | ||
| } | ||
| else { | ||
| data.set(old, 0); | ||
| } | ||
| } | ||
| dataView = new DataView(data.buffer, data.byteOffset, data.byteLength); | ||
| } | ||
| function encodeStringCached(input) { | ||
| const cached = encodeStringCache.get(input); | ||
| if (cached !== undefined) { | ||
| data.set(cached.bytes, cursor); | ||
| cursor += cached.bytes.length; | ||
| cached.epoch = encodeCacheEpoch; | ||
| return; | ||
| } | ||
| const start = cursor; | ||
| const byteLen = Buffer.byteLength(input); | ||
| encodeInteger(majorUtf8String, byteLen); | ||
| cursor += data.write(input, cursor); | ||
| const bytes = Uint8Array.prototype.slice.call(data, start, cursor); | ||
| if (encodeStringCache.size >= 2048) { | ||
| if (encodeCacheSaturated) { | ||
| return; | ||
| } | ||
| let evicted = 0; | ||
| for (const [key, entry] of encodeStringCache) { | ||
| if (evicted >= 1024) { | ||
| break; | ||
| } | ||
| if (entry.epoch !== encodeCacheEpoch) { | ||
| encodeStringCache.delete(key); | ||
| evicted++; | ||
| } | ||
| } | ||
| if (evicted === 0) { | ||
| encodeCacheSaturated = true; | ||
| return; | ||
| } | ||
| } | ||
| if (encodeStringCache.size < 2048) { | ||
| encodeStringCache.set(input, { epoch: encodeCacheEpoch, bytes }); | ||
| } | ||
| } | ||
| function ensureSpace(bytes) { | ||
| const remaining = data.byteLength - cursor; | ||
| if (remaining < bytes) { | ||
| if (cursor < 16_000_000) { | ||
| resize(Math.max(data.byteLength * 4, data.byteLength + bytes)); | ||
| } | ||
| else { | ||
| resize(data.byteLength + bytes + 16_000_000); | ||
| } | ||
| } | ||
| } | ||
| function encodeHeader(major, value) { | ||
| if (value < 24) { | ||
| data[cursor++] = (major << 5) | value; | ||
| } | ||
| else if (value < 256) { | ||
| data[cursor++] = (major << 5) | 24; | ||
| data[cursor++] = value; | ||
| } | ||
| else if (value < 65536) { | ||
| data[cursor++] = (major << 5) | extendedFloat16; | ||
| dataView.setUint16(cursor, value); | ||
| cursor += 2; | ||
| } | ||
| else if (value < 4294967296) { | ||
| data[cursor++] = (major << 5) | extendedFloat32; | ||
| dataView.setUint32(cursor, value); | ||
| cursor += 4; | ||
| } | ||
| else { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| dataView.setBigUint64(cursor, typeof value === "bigint" ? value : BigInt(value)); | ||
| cursor += 8; | ||
| } | ||
| } | ||
| function encodeInteger(major, value) { | ||
| if (value < 24) { | ||
| data[cursor++] = (major << 5) | value; | ||
| } | ||
| else if (value < 256) { | ||
| data[cursor++] = (major << 5) | 24; | ||
| data[cursor++] = value; | ||
| } | ||
| else if (value < 65536) { | ||
| data[cursor++] = (major << 5) | extendedFloat16; | ||
| data[cursor++] = value >> 8; | ||
| data[cursor++] = value & 0xff; | ||
| } | ||
| else if (value < 4294967296) { | ||
| data[cursor++] = (major << 5) | extendedFloat32; | ||
| dataView.setUint32(cursor, value); | ||
| cursor += 4; | ||
| } | ||
| else { | ||
| data[cursor++] = (major << 5) | extendedFloat64; | ||
| const hi = (value / 4294967296) | 0; | ||
| const lo = (value - hi * 4294967296) | 0; | ||
| dataView.setUint32(cursor, hi); | ||
| dataView.setUint32(cursor + 4, lo); | ||
| cursor += 8; | ||
| } | ||
| } |
@@ -1,5 +0,6 @@ | ||
| import { decode, setPayload } from "./cbor-decode"; | ||
| import { encode, resize, toUint8Array } from "./cbor-encode"; | ||
| import { advanceDecodingEpoch, decode, setPayload } from "./cbor-decode"; | ||
| import { advanceEncodingEpoch, encode, resize, toUint8Array } from "./cbor-encode"; | ||
| export const cbor = { | ||
| deserialize(payload) { | ||
| advanceDecodingEpoch(); | ||
| setPayload(payload); | ||
@@ -9,2 +10,3 @@ return decode(0, payload.length); | ||
| serialize(input) { | ||
| advanceEncodingEpoch(); | ||
| try { | ||
@@ -11,0 +13,0 @@ encode(input); |
| export const getValueFromTextNode = (obj) => { | ||
| const textNodeName = "#text"; | ||
| for (const key in obj) { | ||
| if (obj.hasOwnProperty(key) && obj[key][textNodeName] !== undefined) { | ||
| if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key][textNodeName] !== undefined) { | ||
| obj[key] = obj[key][textNodeName]; | ||
@@ -6,0 +6,0 @@ } |
@@ -19,1 +19,5 @@ import { type CborValueType, type Float32, type Uint8, type Uint32 } from "./cbor-types"; | ||
| export declare function bytesToFloat16(a: Uint8, b: Uint8): Float32; | ||
| /** | ||
| * @internal | ||
| */ | ||
| export declare function advanceDecodingEpoch(): void; |
| /** | ||
| * @param _input - JS data object. | ||
| */ | ||
| export declare function encode(_input: any): void; | ||
| /** | ||
| * @internal | ||
| */ | ||
| export declare function advanceEncodingEpoch(): void; | ||
| /** | ||
| * @internal | ||
| */ | ||
| export declare function toUint8Array(): Uint8Array; | ||
| export declare function resize(size: number): void; | ||
| /** | ||
| * @param _input - JS data object. | ||
| */ | ||
| export declare function encode(_input: any): void; |
+1
-1
| { | ||
| "name": "@smithy/core", | ||
| "version": "3.25.1", | ||
| "version": "3.26.0", | ||
| "scripts": { | ||
@@ -5,0 +5,0 @@ "build": "concurrently 'yarn:build:types' 'yarn:build:es:cjs'", |
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
1325042
0.57%32972
0.93%