-
Notifications
You must be signed in to change notification settings - Fork 37
/
utils.ts
104 lines (85 loc) · 2.96 KB
/
utils.ts
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import BigNumber from "bignumber.js";
/**
* Returns whether the most significant bit of a given byte (within a buffer) is 1.
* @param buffer the buffer to test
* @param byteIndex the index of the byte to test
*/
export function isMsbOne(buffer: Buffer, byteIndex: number = 0): boolean {
let byte = buffer[byteIndex];
let bit = byte >> 7;
let isSet = bit == 1;
return isSet;
}
/**
* Returns whether the most significant bit of a given byte (within a buffer) is 0.
* @param buffer the buffer to test
* @param byteIndex the index of the byte to test
*/
export function isMsbZero(buffer: Buffer, byteIndex: number = 0): boolean {
return !isMsbOne(buffer, byteIndex);
}
export function cloneBuffer(buffer: Buffer) {
let clone = Buffer.alloc(buffer.length);
buffer.copy(clone);
return clone;
}
export function bufferToBigInt(buffer: Buffer): BigNumber {
// Currently, in JavaScript, this is the feasible way to achieve reliable, arbitrary-size Buffer to BigInt conversion.
let hex = buffer.toString("hex");
return new BigNumber(`0x${hex}`, 16);
}
export function bigIntToBuffer(value: BigNumber): Buffer {
// Currently, in JavaScript, this is the feasible way to achieve reliable, arbitrary-size BigInt to Buffer conversion.
let hex = getHexMagnitudeOfBigInt(value);
return Buffer.from(hex, "hex");
}
export function getHexMagnitudeOfBigInt(value: BigNumber): string {
if (!value) {
return "";
}
if (value.isNegative()) {
value = value.multipliedBy(new BigNumber(-1));
}
let hex = value.toString(16);
let padding = "0";
if (hex.length % 2 == 1) {
hex = padding + hex;
}
return hex;
}
export function flipBufferBitsInPlace(buffer: Buffer) {
for (let i = 0; i < buffer.length; i++) {
buffer[i] = ~buffer[i];
}
}
export function prependByteToBuffer(buffer: Buffer, byte: number) {
return Buffer.concat([Buffer.from([byte]), buffer]);
}
/**
* Discards the leading bytes that are merely a padding of the leading sign bit (but keeps the payload).
* @param buffer A number, represented as a sequence of bytes (big-endian)
*/
export function discardSuperfluousBytesInTwosComplement(buffer: Buffer): Buffer {
let isNegative = isMsbOne(buffer, 0);
let signPadding: number = isNegative ? 0xFF : 0x00;
let index;
for (index = 0; index < buffer.length - 1; index++) {
let isPaddingByte = buffer[index] == signPadding;
let hasSignBitOnNextByte = isMsbOne(buffer, index + 1) === isNegative;
if (isPaddingByte && hasSignBitOnNextByte) {
continue;
}
break;
}
return buffer.slice(index);
}
/**
* Discards the leading zero bytes.
* @param buffer A number, represented as a sequence of bytes (big-endian)
*/
export function discardSuperfluousZeroBytes(buffer: Buffer): Buffer {
let index;
for (index = 0; index < buffer.length && buffer[index] == 0; index++) {
}
return buffer.slice(index);
}