Skip to content

Commit

Permalink
fix: code generation for int64 map values in fromPartial and fromJson (
Browse files Browse the repository at this point in the history
…#395)

* fix code generation for int64 map values in fromPartial and fromJson

* Add tests and some follow up fixes.

* Fix test.

Co-authored-by: christians <christian.schroeder@consistec.de>
Co-authored-by: Stephen Haberman <stephen.haberman@gmail.com>
  • Loading branch information
3 people committed Nov 21, 2021
1 parent 81d58b0 commit d3ea8eb
Show file tree
Hide file tree
Showing 12 changed files with 319 additions and 61 deletions.
Binary file modified integration/simple-long/google/protobuf/wrappers.bin
Binary file not shown.
16 changes: 5 additions & 11 deletions integration/simple-long/google/protobuf/wrappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,7 @@ export const Int64Value = {

fromPartial(object: DeepPartial<Int64Value>): Int64Value {
const message = { ...baseInt64Value } as Int64Value;
if (object.value !== undefined && object.value !== null) {
message.value = object.value as Long;
} else {
message.value = Long.ZERO;
}
message.value = object.value !== undefined && object.value !== null ? Long.fromValue(object.value) : Long.ZERO;
return message;
},
};
Expand Down Expand Up @@ -281,11 +277,7 @@ export const UInt64Value = {

fromPartial(object: DeepPartial<UInt64Value>): UInt64Value {
const message = { ...baseUInt64Value } as UInt64Value;
if (object.value !== undefined && object.value !== null) {
message.value = object.value as Long;
} else {
message.value = Long.UZERO;
}
message.value = object.value !== undefined && object.value !== null ? Long.fromValue(object.value) : Long.UZERO;
return message;
},
};
Expand Down Expand Up @@ -560,9 +552,11 @@ function base64FromBytes(arr: Uint8Array): string {
return btoa(bin.join(''));
}

type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined | Long;
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Long
? string | number | Long
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
Expand Down
76 changes: 76 additions & 0 deletions integration/simple-long/simple-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { SimpleWithMap } from './simple';

describe('simple', () => {
it('can fromPartial maps', () => {
const s1 = SimpleWithMap.fromPartial({
intLookup: { 1: 2, 2: 1 },
longLookup: { '1': 2, '2': 1 },
});
expect(s1).toMatchInlineSnapshot(`
Object {
"intLookup": Object {
"1": 2,
"2": 1,
},
"longLookup": Object {
"1": Long {
"high": 0,
"low": 2,
"unsigned": false,
},
"2": Long {
"high": 0,
"low": 1,
"unsigned": false,
},
},
"nameLookup": Object {},
}
`);
});

it('can toJSON/fromJSON maps', () => {
const s1 = SimpleWithMap.fromPartial({
intLookup: { 1: 2, 2: 1 },
longLookup: { '1': 2, '2': 1 },
});

const json = SimpleWithMap.toJSON(s1);
expect(json).toMatchInlineSnapshot(`
Object {
"intLookup": Object {
"1": 2,
"2": 1,
},
"longLookup": Object {
"1": "2",
"2": "1",
},
"nameLookup": Object {},
}
`);

const s2 = SimpleWithMap.fromJSON(JSON.parse(JSON.stringify(json)));
expect(s2).toMatchInlineSnapshot(`
Object {
"intLookup": Object {
"1": 2,
"2": 1,
},
"longLookup": Object {
"1": Long {
"high": 0,
"low": 2,
"unsigned": false,
},
"2": Long {
"high": 0,
"low": 1,
"unsigned": false,
},
},
"nameLookup": Object {},
}
`);
});
});
Binary file modified integration/simple-long/simple.bin
Binary file not shown.
2 changes: 2 additions & 0 deletions integration/simple-long/simple.proto
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ message SimpleWithWrappers {
message SimpleWithMap {
map<string, string> nameLookup = 2;
map<int32, int32> intLookup = 3;
// Ideally we'd test map<int64, int64> but we present maps as JS objects and `Long` cannot be used as a keys.
map<string, int64> longLookup = 4;
}

message Numbers {
Expand Down
138 changes: 106 additions & 32 deletions integration/simple-long/simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export interface SimpleWithWrappers {
export interface SimpleWithMap {
nameLookup: { [key: string]: string };
intLookup: { [key: number]: number };
/** Ideally we'd test map<int64, int64> but we present maps as JS objects and `Long` cannot be used as a keys. */
longLookup: { [key: string]: Long };
}

export interface SimpleWithMap_NameLookupEntry {
Expand All @@ -29,6 +31,11 @@ export interface SimpleWithMap_IntLookupEntry {
value: number;
}

export interface SimpleWithMap_LongLookupEntry {
key: string;
value: Long;
}

export interface Numbers {
double: number;
float: number;
Expand Down Expand Up @@ -142,11 +149,8 @@ export const SimpleWithWrappers = {
message.name = object.name ?? undefined;
message.age = object.age ?? undefined;
message.enabled = object.enabled ?? undefined;
if (object.bananas !== undefined && object.bananas !== null) {
message.bananas = object.bananas as Long | undefined;
} else {
message.bananas = undefined;
}
message.bananas =
object.bananas !== undefined && object.bananas !== null ? Long.fromValue(object.bananas) : undefined;
message.coins = (object.coins ?? []).map((e) => e);
message.snacks = (object.snacks ?? []).map((e) => e);
return message;
Expand All @@ -163,6 +167,9 @@ export const SimpleWithMap = {
Object.entries(message.intLookup).forEach(([key, value]) => {
SimpleWithMap_IntLookupEntry.encode({ key: key as any, value }, writer.uint32(26).fork()).ldelim();
});
Object.entries(message.longLookup).forEach(([key, value]) => {
SimpleWithMap_LongLookupEntry.encode({ key: key as any, value }, writer.uint32(34).fork()).ldelim();
});
return writer;
},

Expand All @@ -172,6 +179,7 @@ export const SimpleWithMap = {
const message = { ...baseSimpleWithMap } as SimpleWithMap;
message.nameLookup = {};
message.intLookup = {};
message.longLookup = {};
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
Expand All @@ -187,6 +195,12 @@ export const SimpleWithMap = {
message.intLookup[entry3.key] = entry3.value;
}
break;
case 4:
const entry4 = SimpleWithMap_LongLookupEntry.decode(reader, reader.uint32());
if (entry4.value !== undefined) {
message.longLookup[entry4.key] = entry4.value;
}
break;
default:
reader.skipType(tag & 7);
break;
Expand All @@ -209,6 +223,12 @@ export const SimpleWithMap = {
message.intLookup[Number(key)] = Number(value);
});
}
message.longLookup = {};
if (object.longLookup !== undefined && object.longLookup !== null) {
Object.entries(object.longLookup).forEach(([key, value]) => {
message.longLookup[key] = Long.fromString(value as string);
});
}
return message;
},

Expand All @@ -226,6 +246,12 @@ export const SimpleWithMap = {
obj.intLookup[k] = v;
});
}
obj.longLookup = {};
if (message.longLookup) {
Object.entries(message.longLookup).forEach(([k, v]) => {
obj.longLookup[k] = v.toString();
});
}
return obj;
},

Expand All @@ -247,6 +273,14 @@ export const SimpleWithMap = {
}
});
}
message.longLookup = {};
if (object.longLookup !== undefined && object.longLookup !== null) {
Object.entries(object.longLookup).forEach(([key, value]) => {
if (value !== undefined) {
message.longLookup[key] = Long.fromValue(value);
}
});
}
return message;
},
};
Expand Down Expand Up @@ -363,6 +397,62 @@ export const SimpleWithMap_IntLookupEntry = {
},
};

const baseSimpleWithMap_LongLookupEntry: object = { key: '', value: Long.ZERO };

export const SimpleWithMap_LongLookupEntry = {
encode(message: SimpleWithMap_LongLookupEntry, writer: Writer = Writer.create()): Writer {
if (message.key !== '') {
writer.uint32(10).string(message.key);
}
if (!message.value.isZero()) {
writer.uint32(16).int64(message.value);
}
return writer;
},

decode(input: Reader | Uint8Array, length?: number): SimpleWithMap_LongLookupEntry {
const reader = input instanceof Reader ? input : new Reader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseSimpleWithMap_LongLookupEntry } as SimpleWithMap_LongLookupEntry;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.key = reader.string();
break;
case 2:
message.value = reader.int64() as Long;
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},

fromJSON(object: any): SimpleWithMap_LongLookupEntry {
const message = { ...baseSimpleWithMap_LongLookupEntry } as SimpleWithMap_LongLookupEntry;
message.key = object.key !== undefined && object.key !== null ? String(object.key) : '';
message.value = object.value !== undefined && object.value !== null ? Long.fromString(object.value) : Long.ZERO;
return message;
},

toJSON(message: SimpleWithMap_LongLookupEntry): unknown {
const obj: any = {};
message.key !== undefined && (obj.key = message.key);
message.value !== undefined && (obj.value = (message.value || Long.ZERO).toString());
return obj;
},

fromPartial(object: DeepPartial<SimpleWithMap_LongLookupEntry>): SimpleWithMap_LongLookupEntry {
const message = { ...baseSimpleWithMap_LongLookupEntry } as SimpleWithMap_LongLookupEntry;
message.key = object.key ?? '';
message.value = object.value !== undefined && object.value !== null ? Long.fromValue(object.value) : Long.ZERO;
return message;
},
};

const baseNumbers: object = {
double: 0,
float: 0,
Expand Down Expand Up @@ -535,43 +625,27 @@ export const Numbers = {
message.double = object.double ?? 0;
message.float = object.float ?? 0;
message.int32 = object.int32 ?? 0;
if (object.int64 !== undefined && object.int64 !== null) {
message.int64 = object.int64 as Long;
} else {
message.int64 = Long.ZERO;
}
message.int64 = object.int64 !== undefined && object.int64 !== null ? Long.fromValue(object.int64) : Long.ZERO;
message.uint32 = object.uint32 ?? 0;
if (object.uint64 !== undefined && object.uint64 !== null) {
message.uint64 = object.uint64 as Long;
} else {
message.uint64 = Long.UZERO;
}
message.uint64 = object.uint64 !== undefined && object.uint64 !== null ? Long.fromValue(object.uint64) : Long.UZERO;
message.sint32 = object.sint32 ?? 0;
if (object.sint64 !== undefined && object.sint64 !== null) {
message.sint64 = object.sint64 as Long;
} else {
message.sint64 = Long.ZERO;
}
message.sint64 = object.sint64 !== undefined && object.sint64 !== null ? Long.fromValue(object.sint64) : Long.ZERO;
message.fixed32 = object.fixed32 ?? 0;
if (object.fixed64 !== undefined && object.fixed64 !== null) {
message.fixed64 = object.fixed64 as Long;
} else {
message.fixed64 = Long.UZERO;
}
message.fixed64 =
object.fixed64 !== undefined && object.fixed64 !== null ? Long.fromValue(object.fixed64) : Long.UZERO;
message.sfixed32 = object.sfixed32 ?? 0;
if (object.sfixed64 !== undefined && object.sfixed64 !== null) {
message.sfixed64 = object.sfixed64 as Long;
} else {
message.sfixed64 = Long.ZERO;
}
message.manyUint64 = (object.manyUint64 ?? []).map((e) => e);
message.sfixed64 =
object.sfixed64 !== undefined && object.sfixed64 !== null ? Long.fromValue(object.sfixed64) : Long.ZERO;
message.manyUint64 = (object.manyUint64 ?? []).map((e) => Long.fromValue(e));
return message;
},
};

type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined | Long;
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Long
? string | number | Long
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
Expand Down
5 changes: 5 additions & 0 deletions integration/simple/simple-json-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ describe('simple json', () => {
"intLookup": Object {
"1": 0,
},
"longLookup": Object {},
"mapOfBytes": Object {},
"mapOfStringValues": Object {},
"mapOfTimestamps": Object {},
Expand All @@ -212,6 +213,7 @@ describe('simple json', () => {
Object {
"entitiesById": Object {},
"intLookup": Object {},
"longLookup": Object {},
"mapOfBytes": Object {},
"mapOfStringValues": Object {},
"mapOfTimestamps": Object {
Expand All @@ -236,12 +238,14 @@ describe('simple json', () => {
b: new Uint8Array([1, 2, 3]),
},
mapOfStringValues: {},
longLookup: {},
};
const json = SimpleWithMap.toJSON(s1);
expect(json).toMatchInlineSnapshot(`
Object {
"entitiesById": Object {},
"intLookup": Object {},
"longLookup": Object {},
"mapOfBytes": Object {
"a": "AQI=",
"b": "AQID",
Expand All @@ -265,6 +269,7 @@ describe('simple json', () => {
Object {
"entitiesById": Object {},
"intLookup": Object {},
"longLookup": Object {},
"mapOfBytes": Object {
"a": Uint8Array [
1,
Expand Down
Loading

0 comments on commit d3ea8eb

Please sign in to comment.