All files Stack.ts

100% Statements 31/31
100% Branches 14/14
100% Functions 2/2
100% Lines 30/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 821x             8x 8x 1x           7x       7x 7x 3x 3x       7x     7x 7x 7x     7x 3x   4x                   41x   41x 41x 41x     41x 55x 55x         41x 11x 3x   8x             30x 2x         41x      
export class Stack {
    /**
     * Decodes a number from the stack format (signed magnitude
     * representation).
     * @param buf
     */
    public static decodeNum(buf: Buffer): bigint {
        let result = 0n;
        if (buf.length === 0) {
            return result;
        }
 
        // convert little-endian number to big-endian which swaps around the bytes
        // that occurred during encoding making the negative flag be in the first
        // byte
        const be = Buffer.from(buf).reverse();
 
        // check if the number is negative, which occurs when the 0x80 bit is set
        // on the first number
        let neg = false;
        if (be[0] & 0x80) {
            neg = true;
            be[0] = be[0] & 0x7f; // remove the 0x80 bit
        }
 
        // set result to MSB
        result = BigInt(be[0]);
 
        // read each byte off the buffer
        for (let i = 1; i < be.length; i++) {
            result <<= 8n; // shift right 1-byte
            result += BigInt(be[i]);
        }
 
        if (neg) {
            return -result;
        } else {
            return result;
        }
    }
 
    /**
     * Encodes a number into a stack compatible byte-array. The number
     * is encoded using little-endian signed-magnitude representation.
     * @param num
     */
    public static encodeNum(input: number | bigint): Buffer {
        const num = BigInt(input);
 
        const bytes = [];
        const neg = num < 0;
        let abs = num > 0 ? num : -num;
 
        // push each byte starting with the smallest
        while (abs > 0) {
            bytes.push(Number(abs & BigInt(0xff))); // push on smallest byte
            abs >>= 8n; // shift off smallest byte
        }
 
        // check if the last byte has the 0x80 bit set if so, then we either push
        // a 0 or 0x80 if it is postive or negative
        if (bytes[bytes.length - 1] & 0x80) {
            if (neg) {
                bytes.push(0x80);
            } else {
                bytes.push(0x00);
            }
        }
 
        // if the number is negative we set the 0x80 bit for the number to indicate
        // it is negative
        else {
            if (neg) {
                bytes[bytes.length - 1] |= 0x80;
            }
        }
 
        // return a buffer of the number
        return Buffer.from(bytes);
    }
}