UNPKG

@microsoft/dev-tunnels-ssh

Version:
154 lines 5.81 kB
"use strict"; // // Copyright (c) Microsoft Corporation. All rights reserved. // Object.defineProperty(exports, "__esModule", { value: true }); exports.BigInt = void 0; const buffer_1 = require("buffer"); const sshData_1 = require("./sshData"); /** * Represents a large signed integer as a byte byffer. */ class BigInt { /** * Creates a new BigInt instance from a buffer of signed bytes. * * The first (high) bit of the first (high) byte is the sign bit. Therefore if the * highest byte of an unsigned integer is greater than 127, the bytes must include * a leading zero byte to prevent interpretation as a negative value. */ constructor(buffer) { this.buffer = buffer; if (buffer.length === 0) { throw new Error('BigInt buffer length must be greater than zero.'); } } /** * Gets a value that indicates the sign of the big integer: * 1 for positive, 0 for zero, -1 for negative. */ get sign() { const highByte = this.buffer[0]; if (highByte === 0) { return this.buffer.length > 1 ? 1 : 0; } else { return (highByte & 0x80) === 0 ? 1 : -1; } } static fromInt32(value) { if (value === 0) { return BigInt.zero; } let isNegative = false; if (value < 0) { isNegative = true; value = -value; } const bytes = []; for (let bit = 24; bit >= 0; bit -= 8) { if (value >= 1 << bit || bytes.length > 0) { bytes.push(value >> bit); value = value & ~((1 << bit) - 1); } } if (isNegative) { if ((bytes[0] & 0x80) === 0) { bytes[0] |= 0x80; } else { bytes.splice(0, 0, 0x80); } } return new BigInt(buffer_1.Buffer.from(new Uint8Array(bytes))); } toInt32() { if (this.buffer.length > 4) { throw new TypeError('BigInt value cannot be converted to a 32-bit signed integer.'); } let value = this.buffer[0]; if (this.sign < 0) { value &= 0x7f; } for (let i = 1; i < this.buffer.length; i++) { value = (value << 8) + this.buffer[i]; } if (this.sign < 0) { value = -value; } return value; } /** * Creates a new BigInt instance from a byte buffer. * @param bytes Source byte buffer. * @param options.unsigned True if the bytes should be interpreted as unsigned. If false, * the high bit of the high byte is the sign bit. The default is false. */ static fromBytes(bytes, options) { if (!buffer_1.Buffer.isBuffer(bytes)) { throw new TypeError('Buffer expected.'); } else if (bytes.length === 0) { throw new Error('BigInt buffer length must be greater than zero.'); } options = options !== null && options !== void 0 ? options : {}; const highBit = (bytes[0] & 0x80) !== 0; const prependZeroCount = options.unsigned && highBit ? 1 : 0; let skipZeroCount = 0; // Skip non-significant zeroes at the big end. for (let i = 0; i < bytes.length - 1 && bytes[i] === 0; i++) { if ((bytes[i + 1] & 0x80) === 0) { skipZeroCount++; } } const newBytes = buffer_1.Buffer.alloc(bytes.length + prependZeroCount - skipZeroCount); bytes.copy(newBytes, prependZeroCount, skipZeroCount, bytes.length); return new BigInt(newBytes); } /** * Converts a BigInt instance to a byte buffer. * * @param options.unsigned True if the returned bytes will be interprted as unsigned. * If false, a positive integer may have a leading zero to prevent it from being * interpreted as negative. * @param options.length Desired length of the resulting buffer. The value will be zero- * padded to fill the length. Only applies when `options.unsigned` is true. */ toBytes(options) { options = options !== null && options !== void 0 ? options : {}; let bytes = this.buffer; if (options.unsigned) { if (this.sign < 0) { throw new TypeError('Cannot format a negative BigInt as unsigned.'); } else if (bytes[0] === 0 && bytes.length > 1) { bytes = bytes.slice(1, bytes.length); } if (options.length !== undefined) { if (bytes.length > options.length) { throw new Error(`BigInt (${bytes.length} bytes) is too large for length ${options.length}.`); } else if (bytes.length < options.length) { const padded = buffer_1.Buffer.alloc(options.length); bytes.copy(padded, options.length - bytes.length); return padded; } } } const newBytes = buffer_1.Buffer.alloc(bytes.length); bytes.copy(newBytes, 0, 0, bytes.length); return newBytes; } copyTo(buffer, offset = 0) { this.buffer.copy(buffer, offset, 0, this.buffer.length); } equals(other) { return other instanceof BigInt && this.buffer.equals(other.buffer); } toString(name) { return (0, sshData_1.formatBuffer)(this.buffer, name !== null && name !== void 0 ? name : 'BigInt'); } } exports.BigInt = BigInt; BigInt.zero = new BigInt(buffer_1.Buffer.alloc(1)); //# sourceMappingURL=bigInt.js.map