"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=https://github.com/VSCodium/sourcemaps/releases/download/stable-824c4c46a288b839f13b24022655329c2aeb9f81/node_modules-@microsoft-dev-tunnels-ssh-io-bigInt.js.map