All files Stack.ts

3.23% Statements 1/31
0% Branches 0/14
0% Functions 0/2
3.33% Lines 1/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                                                                                                                                                                  
export class Stack {
  /**
   * Decodes a number from the stack format (signed magnitude
   * representation).
   * @param buf
   */
  public static decodeNum(buf: Buffer): bigint {
    let result = BigInt(0);
    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 <<= BigInt(8); // 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 >>= BigInt(8); // 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);
  }
}