Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support BigInt in binary, compact, json protocols #195

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

kevin-greene-ck
Copy link
Contributor

@kevin-greene-ck kevin-greene-ck commented Jun 5, 2023

Summary

Context

When this library was started the only way to correctly represent 64-bit integers in JavaScript was with Int64 (or another similar library). Because Apache Thrift uses Int64 that is what we stuck with.

At this point JavaScript has supported large integers via BigInt for a while.

Changes

  1. Add support to the various protocols to read/write i64 values stored as BigInt.
  2. Add methods to Int64 to work with BigInt. This includes methods to create a BigInt from an Int64 and create an Int64 from a BigInt.

These changes are optimized toward keeping old code paths unchanged. Changes are still biased toward using Int64. In a later breaking release this will change toward prioritizing BigInt and perhaps removing Int64.

@kevin-greene-ck kevin-greene-ck marked this pull request as ready for review June 5, 2023 13:42
if (typeof i64 === 'number') {
i64 = new Int64(i64)
} else if (typeof i64 === 'string') {
i64 = Int64.fromDecimalString(i64)
}

if (isInt64(i64)) {
if (typeof i64 === 'bigint') {
assertBigIntRange(i64)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

public static MAX_64_BIT_INTEGER = 9_223_372_036_854_775_807n
public static MIN_64_BIT_INTEGER = -9_223_372_036_854_775_808n

public static assert64BitRange(num: bigint): void {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started by adding this method in utils that created a circlular requrie in the generated JS files that because of the way TypeScript enums are generated resulted in null pointer exceptions.

Storing here seems okay for now. Will revisit if we ever remove Int64 support.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is wild lol

public readI64(): Int64 {
public readI64(type?: 'int64'): Int64
public readI64(type: 'bigint'): bigint
public readI64(type?: I64Type): bigint | Int64 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apart from the naming, whats the point of returning a bigint?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand the question. This gets threaded back to the codegen (and ultimately the app code) and based on user options the application is provided with the object they want BigInt or Int64. So we're reading / creating different objects based on what the user wants. More context if looking at the corresponding calls from the codegen PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems weird to me to call readI64 and getting a bigint in return.
i'm also not sure what the usecase is that you would want a bigint, when it'll only even have 64bits of precision

Copy link
Contributor Author

@kevin-greene-ck kevin-greene-ck Jul 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

readI64 here refers purely to the Thrift type we're reading from the Buffer, not the the return type. The goal here is to allow users the option to use a JavaScript primitive value that will satisfy the needs of storing an i64 without having to rely on an external library. It is difficult to do anything useful with an Int64 whereas a BigInt just works with all the usual JS operators. Also, if we were to eventually drop Int64 support the Thrift libraries could be simplified as Buffer already has methods for working with BigInt instead of having to work with the upper and lower bits separately and merging as is now required.

@@ -341,6 +358,10 @@ export class Int64 implements IInt64 {
this.setHiLo({ hi, lo })
}

public toBigInt(): bigint {
return this.buffer.readBigInt64BE()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the return type buffer or bigint?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type is bigint. The readBigInt* methods on Buffer return a bigint reading from Buffer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants