From 3964e575a6bdf90bbde937bcc71ac1f0255831b3 Mon Sep 17 00:00:00 2001 From: Abdulaziz Ghuloum Date: Thu, 29 Dec 2022 19:30:39 +0300 Subject: [PATCH] feat: added bigint force long option (#742) * added bigint force long option * feat: added bigint support * removed commented-out code --- integration/pbjs.sh | 5 + .../google/protobuf/timestamp.ts | 196 ++++++ .../google/protobuf/wrappers.bin | Bin 0 -> 4316 bytes .../google/protobuf/wrappers.proto | 118 ++++ .../google/protobuf/wrappers.ts | 589 ++++++++++++++++++ .../numbers-long-string-test.ts | 164 +++++ integration/simple-long-bigint/parameters.txt | 1 + integration/simple-long-bigint/simple.bin | Bin 0 -> 12009 bytes integration/simple-long-bigint/simple.proto | 22 + integration/simple-long-bigint/simple.ts | 253 ++++++++ src/main.ts | 27 +- src/options.ts | 1 + src/types.ts | 8 + 13 files changed, 1383 insertions(+), 1 deletion(-) create mode 100644 integration/simple-long-bigint/google/protobuf/timestamp.ts create mode 100644 integration/simple-long-bigint/google/protobuf/wrappers.bin create mode 100644 integration/simple-long-bigint/google/protobuf/wrappers.proto create mode 100644 integration/simple-long-bigint/google/protobuf/wrappers.ts create mode 100644 integration/simple-long-bigint/numbers-long-string-test.ts create mode 100644 integration/simple-long-bigint/parameters.txt create mode 100644 integration/simple-long-bigint/simple.bin create mode 100644 integration/simple-long-bigint/simple.proto create mode 100644 integration/simple-long-bigint/simple.ts diff --git a/integration/pbjs.sh b/integration/pbjs.sh index 5f865e37f..d6051ec80 100755 --- a/integration/pbjs.sh +++ b/integration/pbjs.sh @@ -45,6 +45,11 @@ if match "simple-long-string"; then yarn run pbts --no-comments -o integration/simple-long-string/pbjs.d.ts integration/simple-long-string/pbjs.js fi +if match "simple-long-bigint"; then + yarn run pbjs --force-message --force-long -t static-module -o integration/simple-long-bigint/pbjs.js integration/simple-long-bigint/simple.proto + yarn run pbts --no-comments -o integration/simple-long-bigint/pbjs.d.ts integration/simple-long-bigint/pbjs.js +fi + if match "vector-tile"; then yarn run pbjs --force-message --force-number -t static-module -o integration/vector-tile/pbjs.js integration/vector-tile/vector_tile.proto yarn run pbts --no-comments -o integration/vector-tile/pbjs.d.ts integration/vector-tile/pbjs.js diff --git a/integration/simple-long-bigint/google/protobuf/timestamp.ts b/integration/simple-long-bigint/google/protobuf/timestamp.ts new file mode 100644 index 000000000..0ed2e59e1 --- /dev/null +++ b/integration/simple-long-bigint/google/protobuf/timestamp.ts @@ -0,0 +1,196 @@ +/* eslint-disable */ +import * as Long from "long"; +import * as _m0 from "protobufjs/minimal"; + +export const protobufPackage = "google.protobuf"; + +/** + * A Timestamp represents a point in time independent of any time zone or local + * calendar, encoded as a count of seconds and fractions of seconds at + * nanosecond resolution. The count is relative to an epoch at UTC midnight on + * January 1, 1970, in the proleptic Gregorian calendar which extends the + * Gregorian calendar backwards to year one. + * + * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + * second table is needed for interpretation, using a [24-hour linear + * smear](https://developers.google.com/time/smear). + * + * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + * restricting to that range, we ensure that we can convert to and from [RFC + * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + * + * # Examples + * + * Example 1: Compute Timestamp from POSIX `time()`. + * + * Timestamp timestamp; + * timestamp.set_seconds(time(NULL)); + * timestamp.set_nanos(0); + * + * Example 2: Compute Timestamp from POSIX `gettimeofday()`. + * + * struct timeval tv; + * gettimeofday(&tv, NULL); + * + * Timestamp timestamp; + * timestamp.set_seconds(tv.tv_sec); + * timestamp.set_nanos(tv.tv_usec * 1000); + * + * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + * + * FILETIME ft; + * GetSystemTimeAsFileTime(&ft); + * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + * + * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + * Timestamp timestamp; + * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + * + * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + * + * long millis = System.currentTimeMillis(); + * + * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + * .setNanos((int) ((millis % 1000) * 1000000)).build(); + * + * Example 5: Compute Timestamp from Java `Instant.now()`. + * + * Instant now = Instant.now(); + * + * Timestamp timestamp = + * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + * .setNanos(now.getNano()).build(); + * + * Example 6: Compute Timestamp from current time in Python. + * + * timestamp = Timestamp() + * timestamp.GetCurrentTime() + * + * # JSON Mapping + * + * In JSON format, the Timestamp type is encoded as a string in the + * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + * where {year} is always expressed using four digits while {month}, {day}, + * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + * is required. A proto3 JSON serializer should always use UTC (as indicated by + * "Z") when printing the Timestamp type and a proto3 JSON parser should be + * able to accept both UTC and other timezones (as indicated by an offset). + * + * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + * 01:30 UTC on January 15, 2017. + * + * In JavaScript, one can convert a Date object to this format using the + * standard + * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + * method. In Python, a standard `datetime.datetime` object can be converted + * to this format using + * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + * the Joda Time's [`ISODateTimeFormat.dateTime()`]( + * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + * ) to obtain a formatter capable of generating timestamps in this format. + */ +export interface Timestamp { + /** + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + */ + seconds: bigint; + /** + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + */ + nanos: number; +} + +function createBaseTimestamp(): Timestamp { + return { seconds: BigInt("0"), nanos: 0 }; +} + +export const Timestamp = { + encode(message: Timestamp, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.seconds !== BigInt("0")) { + writer.uint32(8).int64(message.seconds.toString()); + } + if (message.nanos !== 0) { + writer.uint32(16).int32(message.nanos); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Timestamp { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseTimestamp(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.seconds = longToBigint(reader.int64() as Long); + break; + case 2: + message.nanos = reader.int32(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Timestamp { + return { + seconds: isSet(object.seconds) ? BigInt(object.seconds) : BigInt("0"), + nanos: isSet(object.nanos) ? Number(object.nanos) : 0, + }; + }, + + toJSON(message: Timestamp): unknown { + const obj: any = {}; + message.seconds !== undefined && (obj.seconds = message.seconds.toString()); + message.nanos !== undefined && (obj.nanos = Math.round(message.nanos)); + return obj; + }, + + fromPartial, I>>(object: I): Timestamp { + const message = createBaseTimestamp(); + message.seconds = object.seconds ?? BigInt("0"); + message.nanos = object.nanos ?? 0; + return message; + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function longToBigint(long: Long) { + return BigInt(long.toString()); +} + +// If you get a compile-error about 'Constructor and ... have no overlap', +// add '--ts_proto_opt=esModuleInterop=true' as a flag when calling 'protoc'. +if (_m0.util.Long !== Long) { + _m0.util.Long = Long as any; + _m0.configure(); +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} diff --git a/integration/simple-long-bigint/google/protobuf/wrappers.bin b/integration/simple-long-bigint/google/protobuf/wrappers.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f34d6ce0cd3a5ebf8b18b31567e0fd536c12f1b GIT binary patch literal 4316 zcmbtXOK;oQ6{a4J6^=6#(_I7xnw)Vum?Tx?fs+o3OuC>X+GZ+CDoNSnObVD1uVfA= z(%{2}i~gD}yJ&wy(ZAG1m;KHq^-AqHz-VFL$9a6`JLjHzsXm@W(IgPN7jcwE!)&~J z6}uM~B2F4|WxH0ZJluLz+EM=U&#%=xgtf17W4S7f?L1Y#Xh+#F5XWwi3GG+v+9eMj zm8kTrWaX2c9aY^AA~(H3ro1F$hUxdOZ;+|XWZ-OYn^1Ko1ZR+WwReM|wV6y|=tiLj zGoi25`^_i{Zm?6EiNKDX#(p@tLFoQW2!NW`sYq^+*(hY1e^s|e(X{aqyUhnDMXvgs zyngBZi;16}XTt`BcPCNchLc5JFVgD^k<8Qk-%{ys<;p?7`SrJ(~IQI z?ye^;MG(o_ESTUpWtjrROCVl45u?EMry>TEH-mt)B`#(l5TloYsyPmI0pu6qP&p55)r&^iRD`Ldm{YO~ z{v+(fgh~;y?*_?&YMCHxs7>UdyYyS^T>1{=k)5*?f>ghZ=a3~t91x7deiKf&Z%^`Z#rFew%@Z<(y6ao zj@cS?bc^}}tKYK?;>g;j-RkJ(k$N4>wqYHcEyMnSIz6U;p9Z!8AZ^{zrEAy#UD!te z&4F!7;>@mNSk|ELn7!_EWcdWlAaotNZOL%2%h7VJ7(MHh%`y)%19dt%G_a0DcXPIM zCd5W@w47xzI7F==(Tg~#YaDdU1EbqA7*CJQoS3%p90@al?SO4E%_lmXqEO(ND-yVn zA|5Z5E=Wc`$=oNseGDV*nKUZEHj8qBl09f07MwTKz5kSGc7<^t=97XBi<3pq!YF(> z6-nYw#B-8YSA(2$TnhO_He{UCaTcgjRZNG%^SA-ejU=;1b5>jzIKJ|Y)6m1~GigU& z1k!WhjszOQ6?zDcFnWl{y8t&ESk3(89L*uU5;(%#N8Di|LbOM;8F%3ly#QAx`hqV4 zPZ~#?LAMyYS&-5tzkP7(Yig;iRlZRk@u;R%zEyru@2ln7H~BDMe5O2+i%+x)5A((6 ziY^zw&?-F47hfoKxmeOFJj@q=t2E>y%=0i`tSdWmQPnCu%okrOc*?;0Z?p;zCu+H> zXw^OCccty0X6eB#CQ~7)KJ(<0?o9SCQ1Q-2g~sB7uk2YjXHL(So_=S97AXb844J}Z zgkPnq0P|jLOC_~hRmzH1d0pPx-r_{#cHnp8oU;vejV0Dtq^1@#XurPy<6pc=Z-HL|fHyTweFFF;hX1y#ZEF&~bg_aS0zm(^ zye{!#2IaT42eTQ_zkRqV(U-MqQ!#Euk5|?AukS{`cnUAj^P?!76y%oypjn_VGy3)% zy>zjH9s)q$F3@8J<#vG{GoWt+Jr_?!tG-i?ZY`edGvO~i4Zl|O%y{?CEW^nV)v8X&wc=wD;}A6Dr9C;&(x zfDZ-zm_hqPK|f{)-~;H7P(S$A7%HN)J-Yeq4)M`-H~aHXvjzEQX`G2O*_6-5cv=d! z!cFKNpbTr9>SLVZdmM;Y-rU}lro&J znckX*{3PBT$kGSoB9xV5ybcII7kOA`_`y66x!g(skU#)Ikq6A69Ta)M3;_hiF{o+P zSjlcZ21EX6y&M1H+x8atH2{cHHW-7c1x?0Q6~b3^0RoS{wt+fIfY=IlLz? H`d9x0-c*59 literal 0 HcmV?d00001 diff --git a/integration/simple-long-bigint/google/protobuf/wrappers.proto b/integration/simple-long-bigint/google/protobuf/wrappers.proto new file mode 100644 index 000000000..01947639a --- /dev/null +++ b/integration/simple-long-bigint/google/protobuf/wrappers.proto @@ -0,0 +1,118 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Wrappers for primitive (non-message) types. These types are useful +// for embedding primitives in the `google.protobuf.Any` type and for places +// where we need to distinguish between the absence of a primitive +// typed field and its default value. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/wrappers"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "WrappersProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// Wrapper message for `double`. +// +// The JSON representation for `DoubleValue` is JSON number. +message DoubleValue { + // The double value. + double value = 1; +} + +// Wrapper message for `float`. +// +// The JSON representation for `FloatValue` is JSON number. +message FloatValue { + // The float value. + float value = 1; +} + +// Wrapper message for `int64`. +// +// The JSON representation for `Int64Value` is JSON string. +message Int64Value { + // The int64 value. + int64 value = 1; +} + +// Wrapper message for `uint64`. +// +// The JSON representation for `UInt64Value` is JSON string. +message UInt64Value { + // The uint64 value. + uint64 value = 1; +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +message Int32Value { + // The int32 value. + int32 value = 1; +} + +// Wrapper message for `uint32`. +// +// The JSON representation for `UInt32Value` is JSON number. +message UInt32Value { + // The uint32 value. + uint32 value = 1; +} + +// Wrapper message for `bool`. +// +// The JSON representation for `BoolValue` is JSON `true` and `false`. +message BoolValue { + // The bool value. + bool value = 1; +} + +// Wrapper message for `string`. +// +// The JSON representation for `StringValue` is JSON string. +message StringValue { + // The string value. + string value = 1; +} + +// Wrapper message for `bytes`. +// +// The JSON representation for `BytesValue` is JSON string. +message BytesValue { + // The bytes value. + bytes value = 1; +} diff --git a/integration/simple-long-bigint/google/protobuf/wrappers.ts b/integration/simple-long-bigint/google/protobuf/wrappers.ts new file mode 100644 index 000000000..f00e50726 --- /dev/null +++ b/integration/simple-long-bigint/google/protobuf/wrappers.ts @@ -0,0 +1,589 @@ +/* eslint-disable */ +import * as Long from "long"; +import * as _m0 from "protobufjs/minimal"; + +export const protobufPackage = "google.protobuf"; + +/** + * Wrapper message for `double`. + * + * The JSON representation for `DoubleValue` is JSON number. + */ +export interface DoubleValue { + /** The double value. */ + value: number; +} + +/** + * Wrapper message for `float`. + * + * The JSON representation for `FloatValue` is JSON number. + */ +export interface FloatValue { + /** The float value. */ + value: number; +} + +/** + * Wrapper message for `int64`. + * + * The JSON representation for `Int64Value` is JSON string. + */ +export interface Int64Value { + /** The int64 value. */ + value: bigint; +} + +/** + * Wrapper message for `uint64`. + * + * The JSON representation for `UInt64Value` is JSON string. + */ +export interface UInt64Value { + /** The uint64 value. */ + value: bigint; +} + +/** + * Wrapper message for `int32`. + * + * The JSON representation for `Int32Value` is JSON number. + */ +export interface Int32Value { + /** The int32 value. */ + value: number; +} + +/** + * Wrapper message for `uint32`. + * + * The JSON representation for `UInt32Value` is JSON number. + */ +export interface UInt32Value { + /** The uint32 value. */ + value: number; +} + +/** + * Wrapper message for `bool`. + * + * The JSON representation for `BoolValue` is JSON `true` and `false`. + */ +export interface BoolValue { + /** The bool value. */ + value: boolean; +} + +/** + * Wrapper message for `string`. + * + * The JSON representation for `StringValue` is JSON string. + */ +export interface StringValue { + /** The string value. */ + value: string; +} + +/** + * Wrapper message for `bytes`. + * + * The JSON representation for `BytesValue` is JSON string. + */ +export interface BytesValue { + /** The bytes value. */ + value: Uint8Array; +} + +function createBaseDoubleValue(): DoubleValue { + return { value: 0 }; +} + +export const DoubleValue = { + encode(message: DoubleValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.value !== 0) { + writer.uint32(9).double(message.value); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): DoubleValue { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseDoubleValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.value = reader.double(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): DoubleValue { + return { value: isSet(object.value) ? Number(object.value) : 0 }; + }, + + toJSON(message: DoubleValue): unknown { + const obj: any = {}; + message.value !== undefined && (obj.value = message.value); + return obj; + }, + + fromPartial, I>>(object: I): DoubleValue { + const message = createBaseDoubleValue(); + message.value = object.value ?? 0; + return message; + }, +}; + +function createBaseFloatValue(): FloatValue { + return { value: 0 }; +} + +export const FloatValue = { + encode(message: FloatValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.value !== 0) { + writer.uint32(13).float(message.value); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): FloatValue { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseFloatValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.value = reader.float(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): FloatValue { + return { value: isSet(object.value) ? Number(object.value) : 0 }; + }, + + toJSON(message: FloatValue): unknown { + const obj: any = {}; + message.value !== undefined && (obj.value = message.value); + return obj; + }, + + fromPartial, I>>(object: I): FloatValue { + const message = createBaseFloatValue(); + message.value = object.value ?? 0; + return message; + }, +}; + +function createBaseInt64Value(): Int64Value { + return { value: BigInt("0") }; +} + +export const Int64Value = { + encode(message: Int64Value, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.value !== BigInt("0")) { + writer.uint32(8).int64(message.value.toString()); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Int64Value { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseInt64Value(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.value = longToBigint(reader.int64() as Long); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Int64Value { + return { value: isSet(object.value) ? BigInt(object.value) : BigInt("0") }; + }, + + toJSON(message: Int64Value): unknown { + const obj: any = {}; + message.value !== undefined && (obj.value = message.value.toString()); + return obj; + }, + + fromPartial, I>>(object: I): Int64Value { + const message = createBaseInt64Value(); + message.value = object.value ?? BigInt("0"); + return message; + }, +}; + +function createBaseUInt64Value(): UInt64Value { + return { value: BigInt("0") }; +} + +export const UInt64Value = { + encode(message: UInt64Value, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.value !== BigInt("0")) { + writer.uint32(8).uint64(message.value.toString()); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): UInt64Value { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseUInt64Value(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.value = longToBigint(reader.uint64() as Long); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): UInt64Value { + return { value: isSet(object.value) ? BigInt(object.value) : BigInt("0") }; + }, + + toJSON(message: UInt64Value): unknown { + const obj: any = {}; + message.value !== undefined && (obj.value = message.value.toString()); + return obj; + }, + + fromPartial, I>>(object: I): UInt64Value { + const message = createBaseUInt64Value(); + message.value = object.value ?? BigInt("0"); + return message; + }, +}; + +function createBaseInt32Value(): Int32Value { + return { value: 0 }; +} + +export const Int32Value = { + encode(message: Int32Value, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.value !== 0) { + writer.uint32(8).int32(message.value); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Int32Value { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseInt32Value(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.value = reader.int32(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Int32Value { + return { value: isSet(object.value) ? Number(object.value) : 0 }; + }, + + toJSON(message: Int32Value): unknown { + const obj: any = {}; + message.value !== undefined && (obj.value = Math.round(message.value)); + return obj; + }, + + fromPartial, I>>(object: I): Int32Value { + const message = createBaseInt32Value(); + message.value = object.value ?? 0; + return message; + }, +}; + +function createBaseUInt32Value(): UInt32Value { + return { value: 0 }; +} + +export const UInt32Value = { + encode(message: UInt32Value, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.value !== 0) { + writer.uint32(8).uint32(message.value); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): UInt32Value { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseUInt32Value(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.value = reader.uint32(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): UInt32Value { + return { value: isSet(object.value) ? Number(object.value) : 0 }; + }, + + toJSON(message: UInt32Value): unknown { + const obj: any = {}; + message.value !== undefined && (obj.value = Math.round(message.value)); + return obj; + }, + + fromPartial, I>>(object: I): UInt32Value { + const message = createBaseUInt32Value(); + message.value = object.value ?? 0; + return message; + }, +}; + +function createBaseBoolValue(): BoolValue { + return { value: false }; +} + +export const BoolValue = { + encode(message: BoolValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.value === true) { + writer.uint32(8).bool(message.value); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): BoolValue { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseBoolValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.value = reader.bool(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): BoolValue { + return { value: isSet(object.value) ? Boolean(object.value) : false }; + }, + + toJSON(message: BoolValue): unknown { + const obj: any = {}; + message.value !== undefined && (obj.value = message.value); + return obj; + }, + + fromPartial, I>>(object: I): BoolValue { + const message = createBaseBoolValue(); + message.value = object.value ?? false; + return message; + }, +}; + +function createBaseStringValue(): StringValue { + return { value: "" }; +} + +export const StringValue = { + encode(message: StringValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.value !== "") { + writer.uint32(10).string(message.value); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): StringValue { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseStringValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.value = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): StringValue { + return { value: isSet(object.value) ? String(object.value) : "" }; + }, + + toJSON(message: StringValue): unknown { + const obj: any = {}; + message.value !== undefined && (obj.value = message.value); + return obj; + }, + + fromPartial, I>>(object: I): StringValue { + const message = createBaseStringValue(); + message.value = object.value ?? ""; + return message; + }, +}; + +function createBaseBytesValue(): BytesValue { + return { value: new Uint8Array() }; +} + +export const BytesValue = { + encode(message: BytesValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.value.length !== 0) { + writer.uint32(10).bytes(message.value); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): BytesValue { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseBytesValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.value = reader.bytes(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): BytesValue { + return { value: isSet(object.value) ? bytesFromBase64(object.value) : new Uint8Array() }; + }, + + toJSON(message: BytesValue): unknown { + const obj: any = {}; + message.value !== undefined && + (obj.value = base64FromBytes(message.value !== undefined ? message.value : new Uint8Array())); + return obj; + }, + + fromPartial, I>>(object: I): BytesValue { + const message = createBaseBytesValue(); + message.value = object.value ?? new Uint8Array(); + return message; + }, +}; + +declare var self: any | undefined; +declare var window: any | undefined; +declare var global: any | undefined; +var tsProtoGlobalThis: any = (() => { + if (typeof globalThis !== "undefined") { + return globalThis; + } + if (typeof self !== "undefined") { + return self; + } + if (typeof window !== "undefined") { + return window; + } + if (typeof global !== "undefined") { + return global; + } + throw "Unable to locate global object"; +})(); + +function bytesFromBase64(b64: string): Uint8Array { + if (tsProtoGlobalThis.Buffer) { + return Uint8Array.from(tsProtoGlobalThis.Buffer.from(b64, "base64")); + } else { + const bin = tsProtoGlobalThis.atob(b64); + const arr = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; ++i) { + arr[i] = bin.charCodeAt(i); + } + return arr; + } +} + +function base64FromBytes(arr: Uint8Array): string { + if (tsProtoGlobalThis.Buffer) { + return tsProtoGlobalThis.Buffer.from(arr).toString("base64"); + } else { + const bin: string[] = []; + arr.forEach((byte) => { + bin.push(String.fromCharCode(byte)); + }); + return tsProtoGlobalThis.btoa(bin.join("")); + } +} + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function longToBigint(long: Long) { + return BigInt(long.toString()); +} + +// If you get a compile-error about 'Constructor and ... have no overlap', +// add '--ts_proto_opt=esModuleInterop=true' as a flag when calling 'protoc'. +if (_m0.util.Long !== Long) { + _m0.util.Long = Long as any; + _m0.configure(); +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} diff --git a/integration/simple-long-bigint/numbers-long-string-test.ts b/integration/simple-long-bigint/numbers-long-string-test.ts new file mode 100644 index 000000000..bbaa19666 --- /dev/null +++ b/integration/simple-long-bigint/numbers-long-string-test.ts @@ -0,0 +1,164 @@ +import { Reader } from 'protobufjs'; +import * as Long from 'long'; +import { Numbers } from './simple'; +import { simple as pbjs, google } from './pbjs'; +import INumbers = pbjs.INumbers; +import PbNumbers = pbjs.Numbers; +import UInt64Value = google.protobuf.UInt64Value; +import PbTimestamp = google.protobuf.Timestamp; + +describe('number', () => { + it('generates types correctly', () => { + const simple: Numbers = { + double: 1, + float: 2, + int32: 3, + int64: BigInt("4"), + uint32: 5, + uint64: BigInt("6"), + sint32: 7, + sint64: BigInt("8"), + fixed32: 9, + fixed64: BigInt("10"), + sfixed32: 11, + sfixed64: BigInt("12"), + guint64: BigInt("13"), + timestamp: new Date('1970-02-03T04:05:06.0071Z') + }; + expect(simple.int64).toEqual(BigInt("4")); + expect(simple.uint64).toEqual(BigInt("6")); + expect(simple.guint64).toEqual(BigInt("13")); + expect(simple.timestamp).toEqual(new Date('1970-02-03T04:05:06.0071Z')) + }); + + it('can decode', () => { + const s1: INumbers = { + double: 1, + float: 2, + int32: 3, + int64: Long.fromNumber(4), + uint32: 5, + uint64: Long.fromNumber(6, true), + sint32: 7, + sint64: Long.fromNumber(8), + fixed32: 9, + fixed64: Long.fromNumber(10, true), + sfixed32: 11, + sfixed64: Long.fromNumber(12), + guint64: new UInt64Value({ value: Long.fromNumber(13, true) }), + timestamp: new PbTimestamp({ + nanos: 7000001, + seconds: Long.fromNumber(1) + }) + }; + const expected: Numbers = { + double: 1, + float: 2, + int32: 3, + int64: BigInt("4"), + uint32: 5, + uint64: BigInt("6"), + sint32: 7, + sint64: BigInt("8"), + fixed32: 9, + fixed64: BigInt("10"), + sfixed32: 11, + sfixed64: BigInt("12"), + guint64: BigInt("13"), + timestamp: new Date('1970-01-01T00:00:01.007000001Z') + }; + const s2 = Numbers.decode(Reader.create(PbNumbers.encode(PbNumbers.fromObject(s1)).finish())); + expect(s2).toEqual(expected); + }); + + it('can encode', () => { + const s1: Numbers = { + double: 1, + float: 2, + int32: 3, + int64: BigInt("4"), + uint32: 5, + uint64: BigInt("6"), + sint32: 7, + sint64: BigInt("8"), + fixed32: 9, + fixed64: BigInt("10"), + sfixed32: 11, + sfixed64: BigInt("12"), + guint64: BigInt("13"), + timestamp: new Date('1980-01-01T00:00:01.123Z') + }; + const expected: INumbers = { + double: 1, + float: 2, + int32: 3, + int64: Long.fromNumber(4), + uint32: 5, + uint64: Long.fromNumber(6, true), + sint32: 7, + sint64: Long.fromNumber(8), + fixed32: 9, + fixed64: Long.fromNumber(10, true), + sfixed32: 11, + sfixed64: Long.fromNumber(12), + guint64: new UInt64Value({ value: Long.fromNumber(13, true) }), + timestamp: new PbTimestamp({ + "nanos": 123000000, + "seconds": Long.fromNumber(315532801) + }) + }; + const s2 = PbNumbers.toObject(PbNumbers.decode(Numbers.encode(s1).finish())); + expect(s2).toEqual({ + ...expected + }); + }); + + it('can decode and fallback to default values', () => { + const s1: INumbers = {}; + const s2 = Numbers.decode(Reader.create(PbNumbers.encode(PbNumbers.fromObject(s1)).finish())); + expect(s2.double).toEqual(0); + expect(s2.float).toEqual(0); + expect(s2.int32).toEqual(0); + expect(s2.int64).toEqual(BigInt("0")); + expect(s2.uint32).toEqual(0); + expect(s2.uint64).toEqual(BigInt("0")); + expect(s2.sint32).toEqual(0); + expect(s2.sint64).toEqual(BigInt("0")); + expect(s2.fixed32).toEqual(0); + expect(s2.fixed64).toEqual(BigInt("0")); + expect(s2.sfixed32).toEqual(0); + expect(s2.guint64).toEqual(undefined); + expect(s2.timestamp).toEqual(undefined) + }); + + it('observes how pbjs handles null', () => { + // the types are in theory only useful for construction + const s1 = PbNumbers.fromObject({ double: null, float: 1 }); + // as after construction, they return the empty string + expect(s1.double).toEqual(0); + const s2 = PbNumbers.decode(PbNumbers.encode(s1).finish()); + expect(s2.double).toEqual(0); + }); + + it('has fromPartial', () => { + const s1 = Numbers.fromPartial({}); + expect(s1).toMatchInlineSnapshot(` + Object { + "double": 0, + "fixed32": 0, + "fixed64": 0n, + "float": 0, + "guint64": undefined, + "int32": 0, + "int64": 0n, + "sfixed32": 0, + "sfixed64": 0n, + "sint32": 0, + "sint64": 0n, + "timestamp": undefined, + "uint32": 0, + "uint64": 0n, + } + `); + }); +}); diff --git a/integration/simple-long-bigint/parameters.txt b/integration/simple-long-bigint/parameters.txt new file mode 100644 index 000000000..8f66a8017 --- /dev/null +++ b/integration/simple-long-bigint/parameters.txt @@ -0,0 +1 @@ +forceLong=bigint diff --git a/integration/simple-long-bigint/simple.bin b/integration/simple-long-bigint/simple.bin new file mode 100644 index 0000000000000000000000000000000000000000..486951c66c1bdf852db9b45c8c771dd674819fbd GIT binary patch literal 12009 zcmeHN&2t;cb;lP;a7c>cP~IqvSKFq{6(EBH5~R2mS3ZCQNI?Ms1^`7%+AVVcG|1T< z%pjNnDN5dB%7?8=m2=M_Ipz@m4X#uw7gwb!ha7Xue~?3t`MvI*0U(j$+PR8FQPbV; zy?*cY>+bi_+N@`Fdp0+Eeb;xFlF9h(#k|^b>7*$93&1=p+LW(5d@<%Q?LQXgUA_ zLpzr~_pX4MRWLih))rfC*LX*}J9EcM{fD$vhtZc0Pc8p!&@=#?J#}rueX**Bpn_F1j=63BrQ=>W4MKVL&!1|Odg6X$5Y_(WmKL4W z2{SOHsQlGFo_wN2k-mgDn&>kNEw)^Yn?)7RLp+q>*rr)NIP zt*!lBA+VCuG8oI-HWOnW>vNCy&w1O>*qQJ5yzOkZ&Cj{*3UgDMAUTCCf{9gdPE2Gq zjn#PD@}T+Vz_(n7nNFJxJPvl4=MMTUE_#}lWA-lvUtWe?Ky%FPi~rpL`0ToEt7ElH zqL5)`pEJzdwS1qq8Rk5<+W7F#Odo$pI@@+Hu+*&OI&F)PJVF8;?r(!7`g!;cV;*xm z0Y@#j%~^Ng`H!+q~q*B5iQ%ay1Wlf zUd;q18_`9;1Y~RvpsJ7$ZOF*~iw}*~fvC3K)}YHBU#OUtBn$n!80j-u3h!H{?G05e z76^kH8(rH_s0zmd0+R?kW|xySb)%p59HC@hG1J>DV<0+vOF)hF9=q!oD{ z48(w0G@h2~tX|z~9Or9AhVR2#^?9jKEU=vy7%Z~g>fwu8Y5!@1J*}1t#af-^D+Tmc z8nx2SQKMR`Yiv1R2kNpI$yZ*m;x7+t#d@7pYpir|ST2DY$k+0fMyXiOuu^5Wd{ih^ z_A?9=Sf$#~Sh;jiY5=ZL&4_8=$79t!c2KPCJ_VWlPN`gKybu%al^PYAY_D3=Se_l` zYmL(GQ8`~@hex%;YQ4xvvO=l8Th5mbiUkAnV@_6lUaT}&{b{~j9v4(&)#FOBM%<5z z$##n1GQU$U(o~rG1&G#)yA2X(__Yh=fx&V{WA(%0ZV6w|M-ghs*Ir~4(R%T(jsS&0 zR>&XZ_ltFwx=AZonBAjV@qoC7D(Xi&^+u_2)F`t3YPBGgT`$(2mv)QwFIl-t>fd8W z^&%K458mNA;3WT&dD1)@nzGjZ(Fe#ws5}GY~xw+=9?>wL;R8trV-Z z7etoyAXXs5j-M9MkA<#CZRJTJbr{EPV-yS%!d9@*LpfQcxL+>q7c09(;-^Yvj!X4o z8VgneZ~H`()O?)Bq%agrOcn{gutfAdV!BW=){~X?SibNaL<#{kETCRe<^rVp(e6{F zb3@DhPm~2$7@fnkQ*gp!XR(yyI;&modFClkGjVkptZ{}*K{mvJjGfvU*qT7)-6n6h z=>QIic)>w)qOJ>UU*Dw*F7I5P2s+{-5Hs6mi{n7Jz!`!qj5CDGQ-BT|P#sv_84d^k zf@2HQIbt?F?%;UDF=Gy=#94qV6X$}(?Y1C}V+N;1#~j!`J15@`X;I6P=&war%^<=}2C5&ggOal${SF8POTl=QSVWI+#uk?rX`yjD zklz^UY*w2fhzSBoYN`e7&FNb~D~{HJu5kzu)f3y1UqqK+ywXJ)7obD#=FR*Mz0zyg zkAi{iq^^Ai_M^o9lbF7w3--knW84D(+&_s;34YN6@{{CT&;s{QZZ8P#V|rpIQoNRX zcvV}QH*-I9g@@deQ{+!sRb#S~-Q0|49?6!&NWxuCd53)~mLJsD42 zPdtkpTx&doAIScQD}N3Daj@`A8Bd(}FNek>Cm9m}5D=iOj0Y`XmzD9L1p&&+coKS| z7CHKm`ZsbvNc}2+7_vWR`!LdYO{qUY>^DZ$zmXf`9suCJq12BSkQ++M*fc&XGsLHvI;rv7&X00ad1N~s?$V1K35j}`>@3hH-ZKZrG& z5guJ?UA=dk2)b_8ei)h!m4D**2mC}F$|oJTmYk^2Av6hAn#l$29(M603DS-&EG>v# zOp}eR1I8gnJ2ok{En2{BPt67`h|!+EEw;gwp7=bsPP|!=kpOZi%GfrZ0t?@$ zb(kXd?Qk6=+?W7>fB?2y2eg1~t93vN0@!LBB=tl;GPrgdG%0Akng3yIdky|^~zkiC1RCx6cV^pMOSNT9op z#-5qZfYR9O8MglTi?vLU^MDIv^B%IrY`@P>T_jVTkb7h~ERf@`k&kS9l+Mtuf@+$r zZ;{a?2$x-Q6UkYJ(ib94-?f|p96*tW*;)(bvt5Ljtjx_`*hM+fWv>f--d;wU6!Sq4 z$7MF4GzG?dlcIe{PKg)Fpdf*O1>$|A6=a4ugUl@DcTDywx4DWGYabbK2V_BmsDGXM zaG`+KGbI# z`ozymgY8^uw2%m`vEE=1C_+R*9hC(RWAO&ig6KuFMQhN0j;l0B(qnwygjZ~Hve6saz6kWPK zEZ4|h5E3IfSNbJ8A(fu)@v<|iscA9H&`&yA$0|G zRz~Ou10ee!n)v3m2Jp;0H`$3?e4{n!_i^ixPzRQcn%;;3&}oX}o_evA*CPbWb%kbt z7xo$szt|aAHmX;tG;QI!yp>XF3aOa1TrAo)1XH0XHLMG zR4~-RqZ@Qka2^N6M14>c|7a3FH0F_oN-0jlK?56qcW5XWr?Xz<(+}_h1Gf%3 zN{;NoRzm%hio~M_J|z`s`;9p+DnTR*vYNPn{;2y$PDQ>8u5=4!bm2?LUYczAE%^=K zt-kG|(0YddahiYEcuSY}ciV5_L*OsYfbU)zZ#!_8=*0c*>zB(x9Y$gkA=ADvFTwn4 zsxnZ4R{8=R@&eixo;`Tv)WCyKGi8{V3dJ`$8QL@(3i-Hf#gxKxdBgkeYR_zoT0XAr z3pb#~&DNRp$%rxXjDJ0_;9(g!ux0v7 z8UtQYppI@qQ077HRF#sd#JwfF$rL=;V74}E!j}OXX)1)FR*h|H*{?R7gHoIt`|+k-#IrEimA z%el4nFX(nyf7Do8-`-f;UVmh)twVj%x^c-+J6JB(Gd=j-0#eM6HzA?l{3wHmDC=L4 z_e2{AM{~W^w|dw=n7rtaMy6zhs@22qXxU+gx&*D{tmp$gq?2wggjpJntl^e7Bw%auAUsVMUUX~cj zj!c4c1Mf}FT$llbktYpo9xkF}iJi28K}t7*kCQ+k5*5!Mlw-=l{#7DEs1uwT9inkE zA`!SYdh%qWTxKq7Tg^TK6Oq6)&it-@UrZa|!ou)Qg5FL@^A7Y#uO`@ol^3fk-PM(L zW98}g%E9(Z-B{_oe1O2h`j%f<9$vuU$RY&|R|)nksXcSsrnvL)3hC7e^iN7^fL)jn z&P5?OHF4p5oszGM@VJQl>~DZ6R)RiOiQTN(v&4dsOw=pH$;vg)zE4}oNt&ezR&oXW zY7F&j7fKeddQ2rJ0vp&?Pizo`ho{`(eN%2VU<#i`m9Ik+gN16^j4YZaeiKE(;_suX zY?}B!8oRUfw^3FLs<3#Eq9RUEr=XFfVThklvL1R_nurh_K6@?g_*|Lm)TY}zs4T*^tSE%sg;n|sqY3SKOIHw@3 z5XrVMn~e0a{uCIK5t3ewcN8XWgU63E2oUKXB~RZ~N)%-}$QdXFg=92Q$dD?FLMgwE zj#M)KL(|5dW$Kgik>=73FEW>Is(&p1LtLAxh?2agf1*vws=IohsajO)5an!9>%fyt z(V$-34jZ|#XqY7#)721c7%lmnArhmv5J^>vLknn0 zRHP*uSeg#eVnCY?(dZGvbchxM+H{D9h8Cj5fu@CMRQuOLv^YVAXbC+&6UvqV+Ds@L z)!b)7+3-{$J`>6Yz}XOOLbQU1CRFO44bdimHXEW%>hZY{Z4zj6;cQe`o(s_?fi@SS zP3iGlA=(tsZiQ%6(7hF+O#$szh=%7p^RZ9V0wjSpADa$ZK%3VVf)>!`@BBzDz_cE} z9s4siG!3-dA=)(1Zii^oK)ZeC6NQF%LJP4!S7;j07GgMv#Hp?UZDD3HXaQ~Ele-EH z30^%!n*o|0qRjwJ57B0TriW-S?8Vs66vbKSbusp7&;r`xy_KK^w8hjzHQSsXzZ0U( a0qsugFBIS$(C+*=K$`>Foz%miJp6wr-`~6d literal 0 HcmV?d00001 diff --git a/integration/simple-long-bigint/simple.proto b/integration/simple-long-bigint/simple.proto new file mode 100644 index 000000000..948c77489 --- /dev/null +++ b/integration/simple-long-bigint/simple.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; +import "google/protobuf/wrappers.proto"; +import "google/protobuf/timestamp.proto"; + +package simple; + +message Numbers { + double double = 1; + float float = 2; + int32 int32 = 3; + int64 int64 = 4; + uint32 uint32 = 5; + uint64 uint64 = 6; + sint32 sint32 = 7; + sint64 sint64 = 8; + fixed32 fixed32 = 9; + fixed64 fixed64 = 10; + sfixed32 sfixed32 = 11; + sfixed64 sfixed64 = 12; + google.protobuf.UInt64Value guint64 = 13; + google.protobuf.Timestamp timestamp = 14; +} diff --git a/integration/simple-long-bigint/simple.ts b/integration/simple-long-bigint/simple.ts new file mode 100644 index 000000000..d5bacab4b --- /dev/null +++ b/integration/simple-long-bigint/simple.ts @@ -0,0 +1,253 @@ +/* eslint-disable */ +import * as Long from "long"; +import * as _m0 from "protobufjs/minimal"; +import { Timestamp } from "./google/protobuf/timestamp"; +import { UInt64Value } from "./google/protobuf/wrappers"; + +export const protobufPackage = "simple"; + +export interface Numbers { + double: number; + float: number; + int32: number; + int64: bigint; + uint32: number; + uint64: bigint; + sint32: number; + sint64: bigint; + fixed32: number; + fixed64: bigint; + sfixed32: number; + sfixed64: bigint; + guint64: bigint | undefined; + timestamp: Date | undefined; +} + +function createBaseNumbers(): Numbers { + return { + double: 0, + float: 0, + int32: 0, + int64: BigInt("0"), + uint32: 0, + uint64: BigInt("0"), + sint32: 0, + sint64: BigInt("0"), + fixed32: 0, + fixed64: BigInt("0"), + sfixed32: 0, + sfixed64: BigInt("0"), + guint64: undefined, + timestamp: undefined, + }; +} + +export const Numbers = { + encode(message: Numbers, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.double !== 0) { + writer.uint32(9).double(message.double); + } + if (message.float !== 0) { + writer.uint32(21).float(message.float); + } + if (message.int32 !== 0) { + writer.uint32(24).int32(message.int32); + } + if (message.int64 !== BigInt("0")) { + writer.uint32(32).int64(message.int64.toString()); + } + if (message.uint32 !== 0) { + writer.uint32(40).uint32(message.uint32); + } + if (message.uint64 !== BigInt("0")) { + writer.uint32(48).uint64(message.uint64.toString()); + } + if (message.sint32 !== 0) { + writer.uint32(56).sint32(message.sint32); + } + if (message.sint64 !== BigInt("0")) { + writer.uint32(64).sint64(message.sint64.toString()); + } + if (message.fixed32 !== 0) { + writer.uint32(77).fixed32(message.fixed32); + } + if (message.fixed64 !== BigInt("0")) { + writer.uint32(81).fixed64(message.fixed64.toString()); + } + if (message.sfixed32 !== 0) { + writer.uint32(93).sfixed32(message.sfixed32); + } + if (message.sfixed64 !== BigInt("0")) { + writer.uint32(97).sfixed64(message.sfixed64.toString()); + } + if (message.guint64 !== undefined) { + UInt64Value.encode({ value: message.guint64! }, writer.uint32(106).fork()).ldelim(); + } + if (message.timestamp !== undefined) { + Timestamp.encode(toTimestamp(message.timestamp), writer.uint32(114).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Numbers { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseNumbers(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.double = reader.double(); + break; + case 2: + message.float = reader.float(); + break; + case 3: + message.int32 = reader.int32(); + break; + case 4: + message.int64 = longToBigint(reader.int64() as Long); + break; + case 5: + message.uint32 = reader.uint32(); + break; + case 6: + message.uint64 = longToBigint(reader.uint64() as Long); + break; + case 7: + message.sint32 = reader.sint32(); + break; + case 8: + message.sint64 = longToBigint(reader.sint64() as Long); + break; + case 9: + message.fixed32 = reader.fixed32(); + break; + case 10: + message.fixed64 = longToBigint(reader.fixed64() as Long); + break; + case 11: + message.sfixed32 = reader.sfixed32(); + break; + case 12: + message.sfixed64 = longToBigint(reader.sfixed64() as Long); + break; + case 13: + message.guint64 = UInt64Value.decode(reader, reader.uint32()).value; + break; + case 14: + message.timestamp = fromTimestamp(Timestamp.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Numbers { + return { + double: isSet(object.double) ? Number(object.double) : 0, + float: isSet(object.float) ? Number(object.float) : 0, + int32: isSet(object.int32) ? Number(object.int32) : 0, + int64: isSet(object.int64) ? BigInt(object.int64) : BigInt("0"), + uint32: isSet(object.uint32) ? Number(object.uint32) : 0, + uint64: isSet(object.uint64) ? BigInt(object.uint64) : BigInt("0"), + sint32: isSet(object.sint32) ? Number(object.sint32) : 0, + sint64: isSet(object.sint64) ? BigInt(object.sint64) : BigInt("0"), + fixed32: isSet(object.fixed32) ? Number(object.fixed32) : 0, + fixed64: isSet(object.fixed64) ? BigInt(object.fixed64) : BigInt("0"), + sfixed32: isSet(object.sfixed32) ? Number(object.sfixed32) : 0, + sfixed64: isSet(object.sfixed64) ? BigInt(object.sfixed64) : BigInt("0"), + guint64: isSet(object.guint64) ? BigInt(object.guint64) : undefined, + timestamp: isSet(object.timestamp) ? fromJsonTimestamp(object.timestamp) : undefined, + }; + }, + + toJSON(message: Numbers): unknown { + const obj: any = {}; + message.double !== undefined && (obj.double = message.double); + message.float !== undefined && (obj.float = message.float); + message.int32 !== undefined && (obj.int32 = Math.round(message.int32)); + message.int64 !== undefined && (obj.int64 = message.int64.toString()); + message.uint32 !== undefined && (obj.uint32 = Math.round(message.uint32)); + message.uint64 !== undefined && (obj.uint64 = message.uint64.toString()); + message.sint32 !== undefined && (obj.sint32 = Math.round(message.sint32)); + message.sint64 !== undefined && (obj.sint64 = message.sint64.toString()); + message.fixed32 !== undefined && (obj.fixed32 = Math.round(message.fixed32)); + message.fixed64 !== undefined && (obj.fixed64 = message.fixed64.toString()); + message.sfixed32 !== undefined && (obj.sfixed32 = Math.round(message.sfixed32)); + message.sfixed64 !== undefined && (obj.sfixed64 = message.sfixed64.toString()); + message.guint64 !== undefined && (obj.guint64 = message.guint64); + message.timestamp !== undefined && (obj.timestamp = message.timestamp.toISOString()); + return obj; + }, + + fromPartial, I>>(object: I): Numbers { + const message = createBaseNumbers(); + message.double = object.double ?? 0; + message.float = object.float ?? 0; + message.int32 = object.int32 ?? 0; + message.int64 = object.int64 ?? BigInt("0"); + message.uint32 = object.uint32 ?? 0; + message.uint64 = object.uint64 ?? BigInt("0"); + message.sint32 = object.sint32 ?? 0; + message.sint64 = object.sint64 ?? BigInt("0"); + message.fixed32 = object.fixed32 ?? 0; + message.fixed64 = object.fixed64 ?? BigInt("0"); + message.sfixed32 = object.sfixed32 ?? 0; + message.sfixed64 = object.sfixed64 ?? BigInt("0"); + message.guint64 = object.guint64 ?? undefined; + message.timestamp = object.timestamp ?? undefined; + return message; + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function toTimestamp(date: Date): Timestamp { + const seconds = BigInt(Math.trunc(date.getTime() / 1_000)); + const nanos = (date.getTime() % 1_000) * 1_000_000; + return { seconds, nanos }; +} + +function fromTimestamp(t: Timestamp): Date { + let millis = Number(t.seconds.toString()) * 1_000; + millis += t.nanos / 1_000_000; + return new Date(millis); +} + +function fromJsonTimestamp(o: any): Date { + if (o instanceof Date) { + return o; + } else if (typeof o === "string") { + return new Date(o); + } else { + return fromTimestamp(Timestamp.fromJSON(o)); + } +} + +function longToBigint(long: Long) { + return BigInt(long.toString()); +} + +// If you get a compile-error about 'Constructor and ... have no overlap', +// add '--ts_proto_opt=esModuleInterop=true' as a flag when calling 'protoc'. +if (_m0.util.Long !== Long) { + _m0.util.Long = Long as any; + _m0.configure(); +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} diff --git a/src/main.ts b/src/main.ts index 08a708f17..6d954efe6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -417,6 +417,15 @@ function makeLongUtils(options: Options, bytes: ReturnType ` ); + const longToBigint = conditionalOutput( + "longToBigint", + code` + function longToBigint(long: ${Long}) { + return BigInt(long.toString()); + } + ` + ); + const longToNumber = conditionalOutput( "longToNumber", code` @@ -429,7 +438,7 @@ function makeLongUtils(options: Options, bytes: ReturnType ` ); - return { numberToLong, longToNumber, longToString, Long }; + return { numberToLong, longToNumber, longToString, longToBigint, Long }; } function makeByteUtils() { @@ -586,6 +595,9 @@ function makeTimestampMethods(options: Options, longs: ReturnType>> 0; const toNumber = getEnumMethod(ctx, field.typeName, "ToNumber"); writeSnippet = (place) => code`writer.uint32(${tag}).${toReaderCall(field)}(${toNumber}(${place}))`; + } else if (isLong(field) && options.forceLong === LongOption.BIGINT) { + const tag = ((field.number << 3) | basicWireType(field.type)) >>> 0; + writeSnippet = (place) => code`writer.uint32(${tag}).${toReaderCall(field)}(${place}.toString())`; } else if (isScalar(field) || isEnum(field)) { const tag = ((field.number << 3) | basicWireType(field.type)) >>> 0; writeSnippet = (place) => code`writer.uint32(${tag}).${toReaderCall(field)}(${place})`; @@ -1261,6 +1278,8 @@ function generateFromJson(ctx: Context, fullName: string, fullTypeName: string, } else if (isLong(field) && options.forceLong === LongOption.LONG) { const cstr = capitalize(basicTypeName(ctx, field, { keepValueType: true }).toCodeString()); return code`${cstr}.fromValue(${from})`; + } else if (isLong(field) && options.forceLong === LongOption.BIGINT) { + return code`BigInt(${from})`; } else { const cstr = capitalize(basicTypeName(ctx, field, { keepValueType: true }).toCodeString()); return code`${cstr}(${from})`; @@ -1285,6 +1304,8 @@ function generateFromJson(ctx: Context, fullName: string, fullTypeName: string, const valueType = valueTypeName(ctx, field.typeName)!; if (isLongValueType(field) && options.forceLong === LongOption.LONG) { return code`${capitalize(valueType.toCodeString())}.fromValue(${from})`; + } else if (isLongValueType(field) && options.forceLong === LongOption.BIGINT) { + return code`BigInt(${from})`; } else if (isBytesValueType(field)) { return code`new ${capitalize(valueType.toCodeString())}(${from})`; } else { @@ -1492,6 +1513,8 @@ function generateToJson( return code`${utils.fromTimestamp}(${from}).toISOString()`; } else if (isLong(valueType) && options.forceLong === LongOption.LONG) { return code`${from}.toString()`; + } else if (isLong(valueType) && options.forceLong === LongOption.BIGINT) { + return code`${from}.toString()`; } else if (isWholeNumber(valueType) && !(isLong(valueType) && options.forceLong === LongOption.STRING)) { return code`Math.round(${from})`; } else if (isScalar(valueType) || isValueType(ctx, valueType)) { @@ -1519,6 +1542,8 @@ function generateToJson( } else if (isLong(field) && options.forceLong === LongOption.LONG) { const v = isWithinOneOf(field) ? "undefined" : defaultValue(ctx, field); return code`(${from} || ${v}).toString()`; + } else if (isLong(field) && options.forceLong === LongOption.BIGINT) { + return code`${from}.toString()`; } else if (isWholeNumber(field) && !(isLong(field) && options.forceLong === LongOption.STRING)) { return code`Math.round(${from})`; } else { diff --git a/src/options.ts b/src/options.ts index e84fa5059..75381f5ab 100644 --- a/src/options.ts +++ b/src/options.ts @@ -6,6 +6,7 @@ export enum LongOption { NUMBER = "number", LONG = "long", STRING = "string", + BIGINT = "bigint", } export enum DateOption { diff --git a/src/types.ts b/src/types.ts index 537a6e6e3..02b42f968 100644 --- a/src/types.ts +++ b/src/types.ts @@ -202,6 +202,8 @@ export function defaultValue(ctx: Context, field: FieldDescriptorProto): any { return code`${utils.Long}.UZERO`; } else if (options.forceLong === LongOption.STRING) { return '"0"'; + } else if (options.forceLong === LongOption.BIGINT) { + return 'BigInt("0")'; } else { return 0; } @@ -212,6 +214,8 @@ export function defaultValue(ctx: Context, field: FieldDescriptorProto): any { return code`${utils.Long}.ZERO`; } else if (options.forceLong === LongOption.STRING) { return '"0"'; + } else if (options.forceLong === LongOption.BIGINT) { + return 'BigInt("0")'; } else { return 0; } @@ -272,6 +276,8 @@ export function notDefaultCheck( return code`${maybeNotUndefinedAnd} !${place}.isZero()`; } else if (options.forceLong === LongOption.STRING) { return code`${maybeNotUndefinedAnd} ${place} !== "0"`; + } else if (options.forceLong === LongOption.BIGINT) { + return code`${maybeNotUndefinedAnd} ${place} !== BigInt("0")`; } else { return code`${maybeNotUndefinedAnd} ${place} !== 0`; } @@ -532,6 +538,8 @@ function longTypeName(ctx: Context): Code { return code`${utils.Long}`; } else if (options.forceLong === LongOption.STRING) { return code`string`; + } else if (options.forceLong === LongOption.BIGINT) { + return code`bigint`; } else { return code`number`; }