Skip to content

Commit

Permalink
fix: Use a Map when map keys are boolean.
Browse files Browse the repository at this point in the history
Fixes #926
  • Loading branch information
stephenh committed Sep 30, 2023
1 parent ccf54be commit 66d39a9
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 21 deletions.
Binary file modified integration/simple/simple.bin
Binary file not shown.
1 change: 1 addition & 0 deletions integration/simple/simple.proto
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ message SimpleWithMap {
map<string, bytes> mapOfBytes = 5;
map<string, google.protobuf.StringValue> mapOfStringValues = 6;
map<int64, int64> longLookup = 7;
map<bool, int64> boolLookup = 8;
}

message SimpleWithSnakeCaseMap {
Expand Down
117 changes: 117 additions & 0 deletions integration/simple/simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ export interface SimpleWithMap {
mapOfBytes: { [key: string]: Uint8Array };
mapOfStringValues: { [key: string]: string | undefined };
longLookup: { [key: number]: number };
boolLookup: Map<boolean, number>;
}

export interface SimpleWithMap_EntitiesByIdEntry {
Expand Down Expand Up @@ -236,6 +237,11 @@ export interface SimpleWithMap_LongLookupEntry {
value: number;
}

export interface SimpleWithMap_BoolLookupEntry {
key: boolean;
value: number;
}

export interface SimpleWithSnakeCaseMap {
entitiesById: { [key: number]: Entity };
}
Expand Down Expand Up @@ -1176,6 +1182,7 @@ function createBaseSimpleWithMap(): SimpleWithMap {
mapOfBytes: {},
mapOfStringValues: {},
longLookup: {},
boolLookup: new Map(),
};
}

Expand Down Expand Up @@ -1204,6 +1211,9 @@ export const SimpleWithMap = {
Object.entries(message.longLookup).forEach(([key, value]) => {
SimpleWithMap_LongLookupEntry.encode({ key: key as any, value }, writer.uint32(58).fork()).ldelim();
});
(message.boolLookup).forEach((value, key) => {
SimpleWithMap_BoolLookupEntry.encode({ key: key as any, value }, writer.uint32(66).fork()).ldelim();
});
return writer;
},

Expand Down Expand Up @@ -1284,6 +1294,16 @@ export const SimpleWithMap = {
message.longLookup[entry7.key] = entry7.value;
}
continue;
case 8:
if (tag !== 66) {
break;
}

const entry8 = SimpleWithMap_BoolLookupEntry.decode(reader, reader.uint32());
if (entry8.value !== undefined) {
message.boolLookup.set(entry8.key, entry8.value);
}
continue;
}
if ((tag & 7) === 4 || tag === 0) {
break;
Expand Down Expand Up @@ -1340,6 +1360,12 @@ export const SimpleWithMap = {
return acc;
}, {})
: {},
boolLookup: isObject(object.boolLookup)
? Object.entries(object.boolLookup).reduce<Map<boolean, number>>((acc, [key, value]) => {
acc.set(globalThis.Boolean(key), Number(value));
return acc;
}, new Map())
: new Map(),
};
},

Expand Down Expand Up @@ -1408,6 +1434,12 @@ export const SimpleWithMap = {
});
}
}
if (message.boolLookup?.size) {
obj.boolLookup = {};
message.boolLookup.forEach((v, k) => {
obj.boolLookup[k] = Math.round(v);
});
}
return obj;
},

Expand Down Expand Up @@ -1478,6 +1510,15 @@ export const SimpleWithMap = {
},
{},
);
message.boolLookup = (() => {
const m = new Map();
(object.boolLookup as Map<boolean, number> ?? new Map()).forEach((value, key) => {
if (value !== undefined) {
m.set(key, Number(value));
}
});
return m;
})();
return message;
},
};
Expand Down Expand Up @@ -2009,6 +2050,82 @@ export const SimpleWithMap_LongLookupEntry = {
},
};

function createBaseSimpleWithMap_BoolLookupEntry(): SimpleWithMap_BoolLookupEntry {
return { key: false, value: 0 };
}

export const SimpleWithMap_BoolLookupEntry = {
encode(message: SimpleWithMap_BoolLookupEntry, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
if (message.key === true) {
writer.uint32(8).bool(message.key);
}
if (message.value !== 0) {
writer.uint32(16).int64(message.value);
}
return writer;
},

decode(input: _m0.Reader | Uint8Array, length?: number): SimpleWithMap_BoolLookupEntry {
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseSimpleWithMap_BoolLookupEntry();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
if (tag !== 8) {
break;
}

message.key = reader.bool();
continue;
case 2:
if (tag !== 16) {
break;
}

message.value = longToNumber(reader.int64() as Long);
continue;
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skipType(tag & 7);
}
return message;
},

fromJSON(object: any): SimpleWithMap_BoolLookupEntry {
return {
key: isSet(object.key) ? Boolean(object.key) : false,
value: isSet(object.value) ? Number(object.value) : 0,
};
},

toJSON(message: SimpleWithMap_BoolLookupEntry): unknown {
const obj: any = {};
if (message.key === true) {
obj.key = message.key;
}
if (message.value !== 0) {
obj.value = Math.round(message.value);
}
return obj;
},

create<I extends Exact<DeepPartial<SimpleWithMap_BoolLookupEntry>, I>>(base?: I): SimpleWithMap_BoolLookupEntry {
return SimpleWithMap_BoolLookupEntry.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<SimpleWithMap_BoolLookupEntry>, I>>(
object: I,
): SimpleWithMap_BoolLookupEntry {
const message = createBaseSimpleWithMap_BoolLookupEntry();
message.key = object.key ?? false;
message.value = object.value ?? 0;
return message;
},
};

function createBaseSimpleWithSnakeCaseMap(): SimpleWithSnakeCaseMap {
return { entitiesById: {} };
}
Expand Down
39 changes: 19 additions & 20 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { code, Code, conditionalOutput, def, imp, joinCode } from "ts-poet";
import {code, Code, conditionalOutput, def, imp, joinCode} from "ts-poet";
import {
DescriptorProto,
FieldDescriptorProto,
Expand All @@ -14,14 +14,12 @@ import {
detectMapType,
getEnumMethod,
isAnyValueType,
isAnyValueTypeName,
isBytes,
isBytesValueType,
isEnum,
isFieldMaskType,
isFieldMaskTypeName,
isListValueType,
isListValueTypeName,
isLong,
isLongValueType,
isMapType,
Expand All @@ -32,31 +30,30 @@ import {
isRepeated,
isScalar,
isStructType,
isStructTypeName,
isTimestamp,
isValueType,
isWholeNumber,
isWithinOneOf,
isWithinOneOfThatShouldBeUnion,
notDefaultCheck,
packedType,
shouldGenerateJSMapType,
toReaderCall,
toTypeName,
shouldGenerateJSMapType,
valueTypeName,
} from "./types";
import SourceInfo, { Fields } from "./sourceInfo";
import SourceInfo, {Fields} from "./sourceInfo";
import {
assertInstanceOf,
getFieldJsonName,
FormattedMethodDescriptor,
getFieldJsonName,
getPropertyAccessor,
impFile,
impProto,
maybeAddComment,
maybePrefixPackage,
getPropertyAccessor,
impFile,
} from "./utils";
import { camelToSnake, capitalize, maybeSnakeToCamel } from "./case";
import {camelToSnake, capitalize, maybeSnakeToCamel} from "./case";
import {
generateNestjsGrpcServiceMethodsDecorator,
generateNestjsServiceClient,
Expand All @@ -75,16 +72,16 @@ import {
generateGrpcMethodDesc,
generateGrpcServiceDesc,
} from "./generate-grpc-web";
import { generateEncodeTransform, generateDecodeTransform } from "./generate-async-iterable";
import { generateEnum } from "./enums";
import { visit, visitServices } from "./visit";
import { addTypeToMessages, DateOption, EnvOption, LongOption, OneofOption, Options, ServiceOption } from "./options";
import { Context } from "./context";
import { generateSchema } from "./schema";
import { ConditionalOutput } from "ts-poet/build/ConditionalOutput";
import { generateGrpcJsService } from "./generate-grpc-js";
import { generateGenericServiceDefinition } from "./generate-generic-service-definition";
import { generateNiceGrpcService } from "./generate-nice-grpc";
import {generateDecodeTransform, generateEncodeTransform} from "./generate-async-iterable";
import {generateEnum} from "./enums";
import {visit, visitServices} from "./visit";
import {addTypeToMessages, DateOption, EnvOption, LongOption, OneofOption, Options, ServiceOption} from "./options";
import {Context} from "./context";
import {generateSchema} from "./schema";
import {ConditionalOutput} from "ts-poet/build/ConditionalOutput";
import {generateGrpcJsService} from "./generate-grpc-js";
import {generateGenericServiceDefinition} from "./generate-generic-service-definition";
import {generateNiceGrpcService} from "./generate-nice-grpc";
import {
generateUnwrapDeep,
generateUnwrapShallow,
Expand Down Expand Up @@ -2287,6 +2284,8 @@ function convertFromObjectKey(
} else {
return code`${ctx.utils.globalThis}.Number(${variableName})`;
}
} else if (keyField.type === FieldDescriptorProto_Type.TYPE_BOOL) {
return code`${ctx.utils.globalThis}.Boolean(${variableName})`;
} else {
return code`${ctx.utils.globalThis}.Number(${variableName})`;
}
Expand Down
5 changes: 4 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,10 @@ export function shouldGenerateJSMapType(ctx: Context, message: DescriptorProto,
if (!mapType) {
return false;
}
return isLong(mapType.keyField) && ctx.options.forceLong === LongOption.LONG;
return (
mapType.keyField.type === FieldDescriptorProto_Type.TYPE_BOOL ||
(isLong(mapType.keyField) && ctx.options.forceLong === LongOption.LONG)
);
}

export function detectMapType(
Expand Down

0 comments on commit 66d39a9

Please sign in to comment.