@creditkarma/thrift-server-core
Version:
Thrift core library in TypeScript
258 lines • 8.16 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.isInt64 = exports.Int64 = void 0;
const POW2_31 = Math.pow(2, 31);
const POW2_32 = Math.pow(2, 32);
const POW10_11 = Math.pow(10, 11);
const _HEX = [];
for (let i = 0; i < 256; i++) {
_HEX[i] = (i > 0xf ? '' : '0') + i.toString(16);
}
const HEX_REGEX = /^(?:0x)?([0-9a-fA-F]+)/;
const BYTE_COUNT = 8;
function hiLoNeg({ hi, lo }) {
const nlo = ~lo + 1;
const carry = nlo === 0 ? 1 : 0;
const nhi = ~hi + carry;
return {
hi: nhi,
lo: nlo,
};
}
function hiLoSignedToUnsigned(i64) {
const negative = i64.hi < 0;
const { hi, lo } = negative ? hiLoNeg(i64) : i64;
return {
negative,
hi: hi >>> 0,
lo: lo >>> 0,
};
}
function hiLoSignedToNumber({ hi, lo }) {
const carry = lo < 0 ? 1 : 0;
return (hi + carry) * POW2_32 + lo;
}
function hiLoSignedFromNumber(i64) {
i64 = Math.trunc(i64);
const lo = i64 >> 0;
const carry = lo < 0 ? 1 : 0;
const hi = (i64 - lo) / POW2_32 - carry;
return { signed: true, hi, lo };
}
function prepBuffer(source, offset) {
if (offset === 0 && source.length === BYTE_COUNT) {
return source;
}
const end = offset >= 0
? offset + BYTE_COUNT
: Math.max(source.length + offset + BYTE_COUNT, 0);
const slice = source.slice(offset, end);
if (slice.length > BYTE_COUNT) {
return slice.slice(0, BYTE_COUNT);
}
if (slice.length === BYTE_COUNT) {
return slice;
}
const out = Buffer.alloc(BYTE_COUNT);
slice.copy(out, BYTE_COUNT - slice.length);
return out;
}
class Int64 {
constructor(...args) {
if (args[0] instanceof Buffer) {
const source = args[0];
const offset = args[1] || 0;
this.buffer = prepBuffer(source, offset);
}
else if (Object.prototype.toString.call(args[0]) === '[object Uint8Array]') {
const source = Buffer.from(args[0]);
const offset = args[1] || 0;
this.buffer = prepBuffer(source, offset);
}
else {
this.buffer = Buffer.alloc(BYTE_COUNT);
this.setValue(args[0], args[1]);
}
}
static toDecimalString(i64) {
if (typeof i64 === 'number') {
return `${i64}`;
}
else {
return i64.toDecimalString();
}
}
static fromDecimalString(text) {
const negative = text.charAt(0) === '-';
if (text.length < (negative ? 17 : 16)) {
return new Int64(+text);
}
else if (text.length > (negative ? 20 : 19)) {
throw new RangeError(`Too many digits for Int64: ${text}`);
}
else {
const high5 = +text.slice(negative ? 1 : 0, -15);
const remainder = +text.slice(-15) + high5 * 2764472320;
const hi = Math.floor(remainder / POW2_32) + high5 * 232830;
const lo = remainder % POW2_32;
if (hi >= POW2_31 &&
!(negative && hi === POW2_31 && lo === 0)) {
throw new RangeError('The magnitude is too large for Int64.');
}
if (negative) {
const neg = hiLoNeg({ hi, lo });
return new Int64(neg.hi, neg.lo);
}
return new Int64(hi, lo);
}
}
setValue(hi, lo) {
if (lo === undefined) {
if (typeof hi === 'number') {
this.setNumber(hi);
return;
}
if (typeof hi === 'string') {
this.setHexString(hi);
return;
}
throw new Error(hi + ' must be a Number or String');
}
if (typeof hi !== 'number' || typeof lo !== 'number') {
throw new Error(`${hi} and ${lo} must be Numbers`);
}
this.setHiLo({ hi, lo });
}
toDecimalString() {
const i64 = this.read();
const value = hiLoSignedToNumber(i64);
if (Number.isSafeInteger(value)) {
return value.toString();
}
const { negative, hi, lo } = hiLoSignedToUnsigned(i64);
const high2 = hi >>> 16;
const low = lo +
(hi & 0x0000ffff) * POW2_32 +
high2 * 74976710656;
const high = Math.floor(low / POW10_11) + high2 * 2814;
const lowStr = ('00000000000' + String(low % POW10_11)).slice(-11);
return (negative ? '-' : '') + String(high) + lowStr;
}
toNumber(allowImprecise = true) {
const x = hiLoSignedToNumber(this.read());
if (!allowImprecise && !Number.isSafeInteger(x)) {
return x < 0 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY;
}
return x;
}
valueOf() {
return this.toNumber(false);
}
toString(radix = 10) {
return this.valueOf().toString(radix);
}
toOctetString(sep = '') {
if (!sep) {
return this.buffer.toString('hex');
}
return Array.from(this.buffer, (num) => _HEX[num]).join(sep);
}
toBuffer(rawBuffer = false) {
if (rawBuffer) {
return this.buffer;
}
const out = Buffer.alloc(BYTE_COUNT);
this.buffer.copy(out);
return out;
}
copy(targetBuffer, targetOffset = 0) {
this.buffer.copy(targetBuffer, targetOffset);
}
compare(other) {
if ((this.buffer[0] & 0x80) !== (other.buffer[0] & 0x80)) {
return other.buffer[0] - this.buffer[0];
}
return this.buffer.compare(other.buffer);
}
equals(other) {
return this.compare(other) === 0;
}
inspect() {
return ('[Int64 value:' + this + ' octets:' + this.toOctetString(' ') + ']');
}
setNumber(i64) {
if (!Number.isFinite(i64)) {
throw new RangeError(`Value is not finite: ${i64}`);
}
const { hi, lo } = hiLoSignedFromNumber(i64);
try {
this.buffer.writeInt32BE(hi, 0);
this.buffer.writeInt32BE(lo, 4);
}
catch {
throw new RangeError(`Value is outside the Int64 range: ${i64}`);
}
}
setHiLo(i64) {
const { hi, lo } = i64;
if (!Number.isInteger(hi)) {
throw new TypeError(`Hi is not an integer: ${hi}`);
}
if (!Number.isInteger(lo)) {
throw new TypeError(`Lo is not an integer: ${lo}`);
}
try {
if (hi < 0) {
this.buffer.writeInt32BE(hi, 0);
}
else {
this.buffer.writeUInt32BE(hi, 0);
}
}
catch {
throw new RangeError(`Hi is outside the Int64 range: ${hi}`);
}
try {
if (lo < 0) {
this.buffer.writeInt32BE(lo, 4);
}
else {
this.buffer.writeUInt32BE(lo, 4);
}
}
catch {
throw new RangeError(`Lo is outside the Int64 range: ${lo}`);
}
}
setHexString(source) {
const matches = source.match(HEX_REGEX);
const match = (matches && matches[1]) || '';
const hex = (match.length % 2 === 0 ? '' : '0') + match;
const length = Buffer.byteLength(hex, 'hex');
if (length > BYTE_COUNT) {
throw new RangeError(source + ' is outside Int64 range');
}
const offset = BYTE_COUNT - length;
this.buffer.fill(0, 0, offset);
this.buffer.write(hex, offset, length, 'hex');
}
read() {
return {
signed: true,
hi: this.buffer.readInt32BE(0),
lo: this.buffer.readInt32BE(4),
};
}
}
exports.Int64 = Int64;
Int64.MAX_INT = Math.pow(2, 53);
Int64.MIN_INT = -Math.pow(2, 53);
function isInt64(i64) {
return (i64 instanceof Int64 ||
(typeof i64 === 'object' &&
i64.buffer instanceof Buffer &&
i64.buffer.length === BYTE_COUNT &&
typeof i64.toDecimalString === 'function'));
}
exports.isInt64 = isInt64;
//# sourceMappingURL=Int64.js.map
;