Skip to content

Commit

Permalink
fix: properly handle loose i64 types during encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin-greene-ck committed Mar 13, 2019
1 parent 3d453b5 commit 9b738e5
Show file tree
Hide file tree
Showing 17 changed files with 37 additions and 193 deletions.
14 changes: 11 additions & 3 deletions src/main/render/thrift-server/struct/encode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { COMMON_IDENTIFIERS, THRIFT_IDENTIFIERS } from '../identifiers'
import { WRITE_METHODS, WriteMethodName } from './methods'

import {
coerceType,
createConstStatement,
createFunctionParameter,
createMethodCall,
Expand Down Expand Up @@ -286,11 +287,18 @@ export function writeValueForType(
case SyntaxType.ByteKeyword:
case SyntaxType.I16Keyword:
case SyntaxType.I32Keyword:
case SyntaxType.I64Keyword:
return [
writeMethodForName(WRITE_METHODS[fieldType.type], fieldName),
]

case SyntaxType.I64Keyword:
return [
writeMethodForName(
WRITE_METHODS[fieldType.type],
coerceType(fieldName, fieldType),
),
]

case SyntaxType.VoidKeyword:
return []

Expand All @@ -302,12 +310,12 @@ export function writeValueForType(

function writeMethodForName(
methodName: WriteMethodName,
fieldName: ts.Identifier,
fieldName: ts.Expression,
): ts.CallExpression {
return createMethodCall('output', methodName, [fieldName])
}

function writeValueForField(
export function writeValueForField(
node: InterfaceWithFields,
fieldType: FunctionType,
fieldName: ts.Identifier,
Expand Down
170 changes: 3 additions & 167 deletions src/main/render/thrift-server/union/encode.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,26 @@
import * as ts from 'typescript'

import {
ContainerType,
FieldDefinition,
FunctionType,
SyntaxType,
UnionDefinition,
} from '@creditkarma/thrift-parser'
import { FieldDefinition, UnionDefinition } from '@creditkarma/thrift-parser'

import { COMMON_IDENTIFIERS, THRIFT_IDENTIFIERS } from '../identifiers'

import { WRITE_METHODS, WriteMethodName } from '../struct/methods'

import {
createTempVariables,
writeFieldBegin,
writeFieldEnd,
writeFieldStop,
writeListBegin,
writeListEnd,
writeMapBegin,
writeMapEnd,
writeSetBegin,
writeSetEnd,
writeStructBegin,
writeStructEnd,
writeValueForIdentifier,
writeValueForField,
} from '../struct/encode'

import {
createFunctionParameter,
createMethodCall,
createNotNullCheck,
isNotVoid,
} from '../utils'

import { createVoidType, typeNodeForFieldType } from '../types'
import { createVoidType } from '../types'

import { IRenderState } from '../../../types'

Expand Down Expand Up @@ -149,152 +134,3 @@ export function createWriteForFieldType(
true,
)
}

export function writeValueForType(
node: UnionDefinition,
fieldType: FunctionType,
fieldName: ts.Identifier,
state: IRenderState,
): Array<ts.Expression> {
switch (fieldType.type) {
case SyntaxType.Identifier:
return writeValueForIdentifier(
state.identifiers[fieldType.value],
node,
fieldType,
fieldName,
state,
)

/**
* Container types:
*
* SetType | MapType | ListType
*/
case SyntaxType.SetType:
return [
writeSetBegin(fieldType, fieldName, state.identifiers),
forEach(node, fieldType, fieldName, state),
writeSetEnd(),
]

case SyntaxType.MapType:
return [
writeMapBegin(fieldType, fieldName, state.identifiers),
forEach(node, fieldType, fieldName, state),
writeMapEnd(),
]

case SyntaxType.ListType:
return [
writeListBegin(fieldType, fieldName, state.identifiers),
forEach(node, fieldType, fieldName, state),
writeListEnd(),
]

/**
* Base types:
*
* SyntaxType.StringKeyword | SyntaxType.DoubleKeyword | SyntaxType.BoolKeyword |
* SyntaxType.I8Keyword | SyntaxType.I16Keyword | SyntaxType.I32Keyword |
* SyntaxType.I64Keyword | SyntaxType.BinaryKeyword | SyntaxType.ByteKeyword
*/
case SyntaxType.BoolKeyword:
case SyntaxType.BinaryKeyword:
case SyntaxType.StringKeyword:
case SyntaxType.DoubleKeyword:
case SyntaxType.I8Keyword:
case SyntaxType.ByteKeyword:
case SyntaxType.I16Keyword:
case SyntaxType.I32Keyword:
case SyntaxType.I64Keyword:
return [
writeMethodForName(WRITE_METHODS[fieldType.type], fieldName),
]

case SyntaxType.VoidKeyword:
return []

default:
const msg: never = fieldType
throw new Error(`Non-exhaustive match for: ${msg}`)
}
}

function writeMethodForName(
methodName: WriteMethodName,
fieldName: ts.Identifier,
): ts.CallExpression {
return createMethodCall('output', methodName, [fieldName])
}

function writeValueForField(
node: UnionDefinition,
fieldType: FunctionType,
fieldName: ts.Identifier,
state: IRenderState,
): Array<ts.ExpressionStatement> {
return writeValueForType(node, fieldType, fieldName, state).map(
ts.createStatement,
)
}

/**
* Loop through container types and write the values for all children
*
* EXAMPLE FOR SET
*
* // thrift
* struct MyStruct {
* 1: required set<string> field1;
* }
*
* // typescript
* obj.field1.forEach((value_1: string): void => {
* output.writeString(value_1);
* });
*/
function forEach(
node: UnionDefinition,
fieldType: ContainerType,
fieldName: ts.Identifier,
state: IRenderState,
): ts.CallExpression {
const value: ts.Identifier = ts.createUniqueName('value')
const forEachParameters: Array<ts.ParameterDeclaration> = [
createFunctionParameter(
value,
typeNodeForFieldType(fieldType.valueType, state),
),
]

const forEachStatements: Array<ts.Statement> = [
...writeValueForField(node, fieldType.valueType, value, state),
]

// If map we have to handle key type as well as value type
if (fieldType.type === SyntaxType.MapType) {
const key: ts.Identifier = ts.createUniqueName('key')
forEachParameters.push(
createFunctionParameter(
key,
typeNodeForFieldType(fieldType.keyType, state),
),
)

forEachStatements.unshift(
...writeValueForField(node, fieldType.keyType, key, state),
)
}

return createMethodCall(fieldName, 'forEach', [
ts.createArrowFunction(
undefined, // modifiers
undefined, // type parameters
forEachParameters, // parameters
createVoidType(), // return type,
ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), // greater than equals token
ts.createBlock(forEachStatements, true), // body
),
])
}
6 changes: 3 additions & 3 deletions src/tests/unit/fixtures/generated/calculator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -697,15 +697,15 @@ export namespace Calculator {
output.writeStructBegin("AddInt64__Args");
if (obj.num1 != null) {
output.writeFieldBegin("num1", thrift.TType.I64, 1);
output.writeI64(obj.num1);
output.writeI64((typeof obj.num1 === "number" ? new thrift.Int64(obj.num1) : typeof obj.num1 === "string" ? thrift.Int64.fromDecimalString(obj.num1) : obj.num1));
output.writeFieldEnd();
}
else {
throw new thrift.TProtocolException(thrift.TProtocolExceptionType.UNKNOWN, "Required field[num1] is unset!");
}
if (obj.num2 != null) {
output.writeFieldBegin("num2", thrift.TType.I64, 2);
output.writeI64(obj.num2);
output.writeI64((typeof obj.num2 === "number" ? new thrift.Int64(obj.num2) : typeof obj.num2 === "string" ? thrift.Int64.fromDecimalString(obj.num2) : obj.num2));
output.writeFieldEnd();
}
else {
Expand Down Expand Up @@ -1939,7 +1939,7 @@ export namespace Calculator {
output.writeStructBegin("AddInt64__Result");
if (obj.success != null) {
output.writeFieldBegin("success", thrift.TType.I64, 0);
output.writeI64(obj.success);
output.writeI64((typeof obj.success === "number" ? new thrift.Int64(obj.success) : typeof obj.success === "string" ? thrift.Int64.fromDecimalString(obj.success) : obj.success));
output.writeFieldEnd();
}
output.writeFieldStop();
Expand Down
2 changes: 1 addition & 1 deletion src/tests/unit/fixtures/generated/shared/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const CodeCodec: thrift.IStructCodec<ICodeArgs, ICode> = {
output.writeStructBegin("Code");
if (obj.status != null) {
output.writeFieldBegin("status", thrift.TType.I64, 1);
output.writeI64(obj.status);
output.writeI64((typeof obj.status === "number" ? new thrift.Int64(obj.status) : typeof obj.status === "string" ? thrift.Int64.fromDecimalString(obj.status) : obj.status));
output.writeFieldEnd();
}
output.writeFieldStop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -726,15 +726,15 @@ export namespace Calculator {
output.writeStructBegin("AddInt64__Args");
if (obj.num1 != null) {
output.writeFieldBegin("num1", thrift.TType.I64, 1);
output.writeI64(obj.num1);
output.writeI64((typeof obj.num1 === "number" ? new thrift.Int64(obj.num1) : typeof obj.num1 === "string" ? thrift.Int64.fromDecimalString(obj.num1) : obj.num1));
output.writeFieldEnd();
}
else {
throw new thrift.TProtocolException(thrift.TProtocolExceptionType.UNKNOWN, "Required field[num1] is unset!");
}
if (obj.num2 != null) {
output.writeFieldBegin("num2", thrift.TType.I64, 2);
output.writeI64(obj.num2);
output.writeI64((typeof obj.num2 === "number" ? new thrift.Int64(obj.num2) : typeof obj.num2 === "string" ? thrift.Int64.fromDecimalString(obj.num2) : obj.num2));
output.writeFieldEnd();
}
else {
Expand Down Expand Up @@ -1968,7 +1968,7 @@ export namespace Calculator {
output.writeStructBegin("AddInt64__Result");
if (obj.success != null) {
output.writeFieldBegin("success", thrift.TType.I64, 0);
output.writeI64(obj.success);
output.writeI64((typeof obj.success === "number" ? new thrift.Int64(obj.success) : typeof obj.success === "string" ? thrift.Int64.fromDecimalString(obj.success) : obj.success));
output.writeFieldEnd();
}
output.writeFieldStop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const CodeCodec: thrift.IStructCodec<ICodeArgs, ICode> = {
output.writeStructBegin("Code");
if (obj.status != null) {
output.writeFieldBegin("status", thrift.TType.I64, 1);
output.writeI64(obj.status);
output.writeI64((typeof obj.status === "number" ? new thrift.Int64(obj.status) : typeof obj.status === "string" ? thrift.Int64.fromDecimalString(obj.status) : obj.status));
output.writeFieldEnd();
}
output.writeFieldStop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const MyStructCodec: thrift.IStructCodec<IMyStructArgs, IMyStruct> = {
}
if (obj.bigID != null) {
output.writeFieldBegin("bigID", thrift.TType.I64, 2);
output.writeI64(obj.bigID);
output.writeI64((typeof obj.bigID === "number" ? new thrift.Int64(obj.bigID) : typeof obj.bigID === "string" ? thrift.Int64.fromDecimalString(obj.bigID) : obj.bigID));
output.writeFieldEnd();
}
output.writeFieldStop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const MyUnionCodec: thrift.IStructCodec<IMyUnionArgs, IMyUnion> = {
if (obj.field2 != null) {
_fieldsSet++;
output.writeFieldBegin("field2", thrift.TType.I64, 2);
output.writeI64(obj.field2);
output.writeI64((typeof obj.field2 === "number" ? new thrift.Int64(obj.field2) : typeof obj.field2 === "string" ? thrift.Int64.fromDecimalString(obj.field2) : obj.field2));
output.writeFieldEnd();
}
output.writeFieldStop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export const MyUnionCodec: thrift.IStructToolkit<MyUnionArgs, MyUnion> = {
if (obj.field2 != null) {
_fieldsSet++;
output.writeFieldBegin("field2", thrift.TType.I64, 2);
output.writeI64(obj.field2);
output.writeI64((typeof obj.field2 === "number" ? new thrift.Int64(obj.field2) : typeof obj.field2 === "string" ? thrift.Int64.fromDecimalString(obj.field2) : obj.field2));
output.writeFieldEnd();
}
output.writeFieldStop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const MyUnionCodec: thrift.IStructCodec<IMyUnionArgs, IMyUnion> = {
if (obj.field2 != null) {
_fieldsSet++;
output.writeFieldBegin("field2", thrift.TType.I64, 2);
output.writeI64(obj.field2);
output.writeI64((typeof obj.field2 === "number" ? new thrift.Int64(obj.field2) : typeof obj.field2 === "string" ? thrift.Int64.fromDecimalString(obj.field2) : obj.field2));
output.writeFieldEnd();
}
output.writeFieldStop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export const MyUnionCodec: thrift.IStructToolkit<MyUnionArgs, MyUnion> = {
if (obj.field2 != null) {
_fieldsSet++;
output.writeFieldBegin("field2", thrift.TType.I64, 2);
output.writeI64(obj.field2);
output.writeI64((typeof obj.field2 === "number" ? new thrift.Int64(obj.field2) : typeof obj.field2 === "string" ? thrift.Int64.fromDecimalString(obj.field2) : obj.field2));
output.writeFieldEnd();
}
output.writeFieldStop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const OtherStructCodec: thrift.IStructCodec<IOtherStructArgs, IOtherStruc
output.writeStructBegin("OtherStruct");
if (obj.id != null) {
output.writeFieldBegin("id", thrift.TType.I64, 1);
output.writeI64(obj.id);
output.writeI64((typeof obj.id === "number" ? new thrift.Int64(obj.id) : typeof obj.id === "string" ? thrift.Int64.fromDecimalString(obj.id) : obj.id));
output.writeFieldEnd();
}
else {
Expand Down Expand Up @@ -197,7 +197,7 @@ export const MyStructCodec: thrift.IStructCodec<IMyStructArgs, IMyStruct> = {
output.writeFieldBegin("intList", thrift.TType.LIST, 5);
output.writeListBegin(thrift.TType.I64, obj.intList.length);
obj.intList.forEach((value_10: number | string | thrift.Int64): void => {
output.writeI64(value_10);
output.writeI64((typeof value_10 === "number" ? new thrift.Int64(value_10) : typeof value_10 === "string" ? thrift.Int64.fromDecimalString(value_10) : value_10));
});
output.writeListEnd();
output.writeFieldEnd();
Expand Down Expand Up @@ -241,8 +241,8 @@ export const MyStructCodec: thrift.IStructCodec<IMyStructArgs, IMyStruct> = {
output.writeFieldBegin("i64KeyedMap", thrift.TType.MAP, 8);
output.writeMapBegin(thrift.TType.I64, thrift.TType.I64, obj.i64KeyedMap.size);
obj.i64KeyedMap.forEach((value_15: number | string | thrift.Int64, key_3: number | string | thrift.Int64): void => {
output.writeI64(key_3);
output.writeI64(value_15);
output.writeI64((typeof key_3 === "number" ? new thrift.Int64(key_3) : typeof key_3 === "string" ? thrift.Int64.fromDecimalString(key_3) : key_3));
output.writeI64((typeof value_15 === "number" ? new thrift.Int64(value_15) : typeof value_15 === "string" ? thrift.Int64.fromDecimalString(value_15) : value_15));
});
output.writeMapEnd();
output.writeFieldEnd();
Expand Down
Loading

0 comments on commit 9b738e5

Please sign in to comment.