From 33f89bfcf0d5d9e64a6fd360eaefc140055e9291 Mon Sep 17 00:00:00 2001 From: TJT Date: Sun, 5 Jun 2022 22:11:25 +0800 Subject: [PATCH] fix: Struct wrap/unwrap snake case #579 (#588) * fix: Struct wrap/unwrap snake case #579 * test: Add more tests about struct snake case * style: format src/main.ts Co-authored-by: TJT --- .../google/protobuf/struct.ts | 515 ++++++++++++++++++ integration/oneof-unions-snake/parameters.txt | 1 + .../oneof-unions-snake/simple-snake-test.ts | 12 + integration/oneof-unions-snake/simple.proto | 9 + integration/oneof-unions-snake/simple.ts | 94 ++++ .../simple-snake/google/protobuf/struct.ts | 478 ++++++++++++++++ integration/simple-snake/simple-snake-test.ts | 11 +- integration/simple-snake/simple.bin | Bin 17257 -> 21936 bytes integration/simple-snake/simple.proto | 7 +- integration/simple-snake/simple.ts | 54 ++ src/main.ts | 93 ++-- 11 files changed, 1234 insertions(+), 40 deletions(-) create mode 100644 integration/oneof-unions-snake/google/protobuf/struct.ts create mode 100644 integration/oneof-unions-snake/parameters.txt create mode 100644 integration/oneof-unions-snake/simple-snake-test.ts create mode 100644 integration/oneof-unions-snake/simple.proto create mode 100644 integration/oneof-unions-snake/simple.ts create mode 100644 integration/simple-snake/google/protobuf/struct.ts diff --git a/integration/oneof-unions-snake/google/protobuf/struct.ts b/integration/oneof-unions-snake/google/protobuf/struct.ts new file mode 100644 index 000000000..4896a1507 --- /dev/null +++ b/integration/oneof-unions-snake/google/protobuf/struct.ts @@ -0,0 +1,515 @@ +/* eslint-disable */ +import * as Long from 'long'; +import * as _m0 from 'protobufjs/minimal'; + +export const protobufPackage = 'google.protobuf'; + +/** + * `NullValue` is a singleton enumeration to represent the null value for the + * `Value` type union. + * + * The JSON representation for `NullValue` is JSON `null`. + */ +export enum NullValue { + /** NULL_VALUE - Null value. */ + NULL_VALUE = 0, + UNRECOGNIZED = -1, +} + +export function nullValueFromJSON(object: any): NullValue { + switch (object) { + case 0: + case 'NULL_VALUE': + return NullValue.NULL_VALUE; + case -1: + case 'UNRECOGNIZED': + default: + return NullValue.UNRECOGNIZED; + } +} + +export function nullValueToJSON(object: NullValue): string { + switch (object) { + case NullValue.NULL_VALUE: + return 'NULL_VALUE'; + case NullValue.UNRECOGNIZED: + default: + return 'UNRECOGNIZED'; + } +} + +/** + * `Struct` represents a structured data value, consisting of fields + * which map to dynamically typed values. In some languages, `Struct` + * might be supported by a native representation. For example, in + * scripting languages like JS a struct is represented as an + * object. The details of that representation are described together + * with the proto support for the language. + * + * The JSON representation for `Struct` is JSON object. + */ +export interface Struct { + /** Unordered map of dynamically typed values. */ + fields: { [key: string]: any | undefined }; +} + +export interface Struct_FieldsEntry { + key: string; + value: any | undefined; +} + +/** + * `Value` represents a dynamically typed value which can be either + * null, a number, a string, a boolean, a recursive struct value, or a + * list of values. A producer of value is expected to set one of these + * variants. Absence of any variant indicates an error. + * + * The JSON representation for `Value` is JSON value. + */ +export interface Value { + kind?: + | { $case: 'null_value'; null_value: NullValue } + | { $case: 'number_value'; number_value: number } + | { $case: 'string_value'; string_value: string } + | { $case: 'bool_value'; bool_value: boolean } + | { $case: 'struct_value'; struct_value: { [key: string]: any } | undefined } + | { $case: 'list_value'; list_value: Array | undefined }; +} + +/** + * `ListValue` is a wrapper around a repeated field of values. + * + * The JSON representation for `ListValue` is JSON array. + */ +export interface ListValue { + /** Repeated field of dynamically typed values. */ + values: any[]; +} + +function createBaseStruct(): Struct { + return { fields: {} }; +} + +export const Struct = { + encode(message: Struct, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + Object.entries(message.fields).forEach(([key, value]) => { + if (value !== undefined) { + Struct_FieldsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).ldelim(); + } + }); + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Struct { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseStruct(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + const entry1 = Struct_FieldsEntry.decode(reader, reader.uint32()); + if (entry1.value !== undefined) { + message.fields[entry1.key] = entry1.value; + } + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Struct { + return { + fields: isObject(object.fields) + ? Object.entries(object.fields).reduce<{ [key: string]: any | undefined }>((acc, [key, value]) => { + acc[key] = value as any | undefined; + return acc; + }, {}) + : {}, + }; + }, + + toJSON(message: Struct): unknown { + const obj: any = {}; + obj.fields = {}; + if (message.fields) { + Object.entries(message.fields).forEach(([k, v]) => { + obj.fields[k] = v; + }); + } + return obj; + }, + + fromPartial, I>>(object: I): Struct { + const message = createBaseStruct(); + message.fields = Object.entries(object.fields ?? {}).reduce<{ [key: string]: any | undefined }>( + (acc, [key, value]) => { + if (value !== undefined) { + acc[key] = value; + } + return acc; + }, + {} + ); + return message; + }, + + wrap(object: { [key: string]: any } | undefined): Struct { + const struct = createBaseStruct(); + if (object !== undefined) { + Object.keys(object).forEach((key) => { + struct.fields[key] = object[key]; + }); + } + return struct; + }, + + unwrap(message: Struct): { [key: string]: any } { + const object: { [key: string]: any } = {}; + Object.keys(message.fields).forEach((key) => { + object[key] = message.fields[key]; + }); + return object; + }, +}; + +function createBaseStruct_FieldsEntry(): Struct_FieldsEntry { + return { key: '', value: undefined }; +} + +export const Struct_FieldsEntry = { + encode(message: Struct_FieldsEntry, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.key !== '') { + writer.uint32(10).string(message.key); + } + if (message.value !== undefined) { + Value.encode(Value.wrap(message.value), writer.uint32(18).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Struct_FieldsEntry { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseStruct_FieldsEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.key = reader.string(); + break; + case 2: + message.value = Value.unwrap(Value.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Struct_FieldsEntry { + return { + key: isSet(object.key) ? String(object.key) : '', + value: isSet(object?.value) ? object.value : undefined, + }; + }, + + toJSON(message: Struct_FieldsEntry): unknown { + const obj: any = {}; + message.key !== undefined && (obj.key = message.key); + message.value !== undefined && (obj.value = message.value); + return obj; + }, + + fromPartial, I>>(object: I): Struct_FieldsEntry { + const message = createBaseStruct_FieldsEntry(); + message.key = object.key ?? ''; + message.value = object.value ?? undefined; + return message; + }, +}; + +function createBaseValue(): Value { + return { kind: undefined }; +} + +export const Value = { + encode(message: Value, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.kind?.$case === 'null_value') { + writer.uint32(8).int32(message.kind.null_value); + } + if (message.kind?.$case === 'number_value') { + writer.uint32(17).double(message.kind.number_value); + } + if (message.kind?.$case === 'string_value') { + writer.uint32(26).string(message.kind.string_value); + } + if (message.kind?.$case === 'bool_value') { + writer.uint32(32).bool(message.kind.bool_value); + } + if (message.kind?.$case === 'struct_value') { + Struct.encode(Struct.wrap(message.kind.struct_value), writer.uint32(42).fork()).ldelim(); + } + if (message.kind?.$case === 'list_value') { + ListValue.encode(ListValue.wrap(message.kind.list_value), writer.uint32(50).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Value { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.kind = { $case: 'null_value', null_value: reader.int32() as any }; + break; + case 2: + message.kind = { $case: 'number_value', number_value: reader.double() }; + break; + case 3: + message.kind = { $case: 'string_value', string_value: reader.string() }; + break; + case 4: + message.kind = { $case: 'bool_value', bool_value: reader.bool() }; + break; + case 5: + message.kind = { $case: 'struct_value', struct_value: Struct.unwrap(Struct.decode(reader, reader.uint32())) }; + break; + case 6: + message.kind = { + $case: 'list_value', + list_value: ListValue.unwrap(ListValue.decode(reader, reader.uint32())), + }; + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Value { + return { + kind: isSet(object.null_value) + ? { $case: 'null_value', null_value: nullValueFromJSON(object.null_value) } + : isSet(object.number_value) + ? { $case: 'number_value', number_value: Number(object.number_value) } + : isSet(object.string_value) + ? { $case: 'string_value', string_value: String(object.string_value) } + : isSet(object.bool_value) + ? { $case: 'bool_value', bool_value: Boolean(object.bool_value) } + : isSet(object.struct_value) + ? { $case: 'struct_value', struct_value: object.struct_value } + : isSet(object.list_value) + ? { $case: 'list_value', list_value: [...object.list_value] } + : undefined, + }; + }, + + toJSON(message: Value): unknown { + const obj: any = {}; + message.kind?.$case === 'null_value' && + (obj.null_value = message.kind?.null_value !== undefined ? nullValueToJSON(message.kind?.null_value) : undefined); + message.kind?.$case === 'number_value' && (obj.number_value = message.kind?.number_value); + message.kind?.$case === 'string_value' && (obj.string_value = message.kind?.string_value); + message.kind?.$case === 'bool_value' && (obj.bool_value = message.kind?.bool_value); + message.kind?.$case === 'struct_value' && (obj.struct_value = message.kind?.struct_value); + message.kind?.$case === 'list_value' && (obj.list_value = message.kind?.list_value); + return obj; + }, + + fromPartial, I>>(object: I): Value { + const message = createBaseValue(); + if ( + object.kind?.$case === 'null_value' && + object.kind?.null_value !== undefined && + object.kind?.null_value !== null + ) { + message.kind = { $case: 'null_value', null_value: object.kind.null_value }; + } + if ( + object.kind?.$case === 'number_value' && + object.kind?.number_value !== undefined && + object.kind?.number_value !== null + ) { + message.kind = { $case: 'number_value', number_value: object.kind.number_value }; + } + if ( + object.kind?.$case === 'string_value' && + object.kind?.string_value !== undefined && + object.kind?.string_value !== null + ) { + message.kind = { $case: 'string_value', string_value: object.kind.string_value }; + } + if ( + object.kind?.$case === 'bool_value' && + object.kind?.bool_value !== undefined && + object.kind?.bool_value !== null + ) { + message.kind = { $case: 'bool_value', bool_value: object.kind.bool_value }; + } + if ( + object.kind?.$case === 'struct_value' && + object.kind?.struct_value !== undefined && + object.kind?.struct_value !== null + ) { + message.kind = { $case: 'struct_value', struct_value: object.kind.struct_value }; + } + if ( + object.kind?.$case === 'list_value' && + object.kind?.list_value !== undefined && + object.kind?.list_value !== null + ) { + message.kind = { $case: 'list_value', list_value: object.kind.list_value }; + } + return message; + }, + + wrap(value: any): Value { + const result = createBaseValue(); + + if (value === null) { + result.kind = { $case: 'null_value', null_value: NullValue.NULL_VALUE }; + } else if (typeof value === 'boolean') { + result.kind = { $case: 'bool_value', bool_value: value }; + } else if (typeof value === 'number') { + result.kind = { $case: 'number_value', number_value: value }; + } else if (typeof value === 'string') { + result.kind = { $case: 'string_value', string_value: value }; + } else if (Array.isArray(value)) { + result.kind = { $case: 'list_value', list_value: value }; + } else if (typeof value === 'object') { + result.kind = { $case: 'struct_value', struct_value: value }; + } else if (typeof value !== 'undefined') { + throw new Error('Unsupported any value type: ' + typeof value); + } + + return result; + }, + + unwrap(message: Value): string | number | boolean | Object | null | Array | undefined { + if (message.kind?.$case === 'null_value') { + return null; + } else if (message.kind?.$case === 'number_value') { + return message.kind?.number_value; + } else if (message.kind?.$case === 'string_value') { + return message.kind?.string_value; + } else if (message.kind?.$case === 'bool_value') { + return message.kind?.bool_value; + } else if (message.kind?.$case === 'struct_value') { + return message.kind?.struct_value; + } else if (message.kind?.$case === 'list_value') { + return message.kind?.list_value; + } else { + return undefined; + } + }, +}; + +function createBaseListValue(): ListValue { + return { values: [] }; +} + +export const ListValue = { + encode(message: ListValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + for (const v of message.values) { + Value.encode(Value.wrap(v!), writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): ListValue { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseListValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.values.push(Value.unwrap(Value.decode(reader, reader.uint32()))); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): ListValue { + return { + values: Array.isArray(object?.values) ? [...object.values] : [], + }; + }, + + toJSON(message: ListValue): unknown { + const obj: any = {}; + if (message.values) { + obj.values = message.values.map((e) => e); + } else { + obj.values = []; + } + return obj; + }, + + fromPartial, I>>(object: I): ListValue { + const message = createBaseListValue(); + message.values = object.values?.map((e) => e) || []; + return message; + }, + + wrap(value: Array | undefined): ListValue { + const result = createBaseListValue(); + + result.values = value ?? []; + + return result; + }, + + unwrap(message: ListValue): Array { + return message.values; + }, +}; + +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 { $case: string } + ? { [K in keyof Omit]?: DeepPartial } & { $case: T['$case'] } + : 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 } & Record>, never>; + +// 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 isObject(value: any): boolean { + return typeof value === 'object' && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} diff --git a/integration/oneof-unions-snake/parameters.txt b/integration/oneof-unions-snake/parameters.txt new file mode 100644 index 000000000..c3bcb3ca8 --- /dev/null +++ b/integration/oneof-unions-snake/parameters.txt @@ -0,0 +1 @@ +snakeToCamel=false,oneof=unions diff --git a/integration/oneof-unions-snake/simple-snake-test.ts b/integration/oneof-unions-snake/simple-snake-test.ts new file mode 100644 index 000000000..24cca56dd --- /dev/null +++ b/integration/oneof-unions-snake/simple-snake-test.ts @@ -0,0 +1,12 @@ +import { SimpleStruct } from './simple'; + +describe('oneof=unions,snakeToCamel=false', () => { + it('struct snake case', () => { + const simple: SimpleStruct = { + simple_struct: { + any: 'any' + } + } + expect(simple.simple_struct!['any']).toEqual('any') + }) +}); diff --git a/integration/oneof-unions-snake/simple.proto b/integration/oneof-unions-snake/simple.proto new file mode 100644 index 000000000..1fae26901 --- /dev/null +++ b/integration/oneof-unions-snake/simple.proto @@ -0,0 +1,9 @@ +// Adding a comment to the syntax will become the first +// comment in the output source file. +syntax = "proto3"; +import "google/protobuf/struct.proto"; +package simple; + +message SimpleStruct { + google.protobuf.Struct simple_struct = 1; +} diff --git a/integration/oneof-unions-snake/simple.ts b/integration/oneof-unions-snake/simple.ts new file mode 100644 index 000000000..18be427ac --- /dev/null +++ b/integration/oneof-unions-snake/simple.ts @@ -0,0 +1,94 @@ +/* eslint-disable */ +import * as Long from 'long'; +import * as _m0 from 'protobufjs/minimal'; +import { Struct } from './google/protobuf/struct'; + +export const protobufPackage = 'simple'; + +/** + * Adding a comment to the syntax will become the first + * comment in the output source file. + */ + +export interface SimpleStruct { + simple_struct: { [key: string]: any } | undefined; +} + +function createBaseSimpleStruct(): SimpleStruct { + return { simple_struct: undefined }; +} + +export const SimpleStruct = { + encode(message: SimpleStruct, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.simple_struct !== undefined) { + Struct.encode(Struct.wrap(message.simple_struct), writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): SimpleStruct { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseSimpleStruct(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.simple_struct = Struct.unwrap(Struct.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): SimpleStruct { + return { + simple_struct: isObject(object.simple_struct) ? object.simple_struct : undefined, + }; + }, + + toJSON(message: SimpleStruct): unknown { + const obj: any = {}; + message.simple_struct !== undefined && (obj.simple_struct = message.simple_struct); + return obj; + }, + + fromPartial, I>>(object: I): SimpleStruct { + const message = createBaseSimpleStruct(); + message.simple_struct = object.simple_struct ?? 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 { $case: string } + ? { [K in keyof Omit]?: DeepPartial } & { $case: T['$case'] } + : 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 } & Record>, never>; + +// 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 isObject(value: any): boolean { + return typeof value === 'object' && value !== null; +} diff --git a/integration/simple-snake/google/protobuf/struct.ts b/integration/simple-snake/google/protobuf/struct.ts new file mode 100644 index 000000000..e6e54254c --- /dev/null +++ b/integration/simple-snake/google/protobuf/struct.ts @@ -0,0 +1,478 @@ +/* eslint-disable */ +import * as Long from 'long'; +import * as _m0 from 'protobufjs/minimal'; + +export const protobufPackage = 'google.protobuf'; + +/** + * `NullValue` is a singleton enumeration to represent the null value for the + * `Value` type union. + * + * The JSON representation for `NullValue` is JSON `null`. + */ +export enum NullValue { + /** NULL_VALUE - Null value. */ + NULL_VALUE = 0, + UNRECOGNIZED = -1, +} + +export function nullValueFromJSON(object: any): NullValue { + switch (object) { + case 0: + case 'NULL_VALUE': + return NullValue.NULL_VALUE; + case -1: + case 'UNRECOGNIZED': + default: + return NullValue.UNRECOGNIZED; + } +} + +export function nullValueToJSON(object: NullValue): string { + switch (object) { + case NullValue.NULL_VALUE: + return 'NULL_VALUE'; + case NullValue.UNRECOGNIZED: + default: + return 'UNRECOGNIZED'; + } +} + +/** + * `Struct` represents a structured data value, consisting of fields + * which map to dynamically typed values. In some languages, `Struct` + * might be supported by a native representation. For example, in + * scripting languages like JS a struct is represented as an + * object. The details of that representation are described together + * with the proto support for the language. + * + * The JSON representation for `Struct` is JSON object. + */ +export interface Struct { + /** Unordered map of dynamically typed values. */ + fields: { [key: string]: any | undefined }; +} + +export interface Struct_FieldsEntry { + key: string; + value: any | undefined; +} + +/** + * `Value` represents a dynamically typed value which can be either + * null, a number, a string, a boolean, a recursive struct value, or a + * list of values. A producer of value is expected to set one of these + * variants. Absence of any variant indicates an error. + * + * The JSON representation for `Value` is JSON value. + */ +export interface Value { + /** Represents a null value. */ + null_value: NullValue | undefined; + /** Represents a double value. */ + number_value: number | undefined; + /** Represents a string value. */ + string_value: string | undefined; + /** Represents a boolean value. */ + bool_value: boolean | undefined; + /** Represents a structured value. */ + struct_value: { [key: string]: any } | undefined; + /** Represents a repeated `Value`. */ + list_value: Array | undefined; +} + +/** + * `ListValue` is a wrapper around a repeated field of values. + * + * The JSON representation for `ListValue` is JSON array. + */ +export interface ListValue { + /** Repeated field of dynamically typed values. */ + values: any[]; +} + +function createBaseStruct(): Struct { + return { fields: {} }; +} + +export const Struct = { + encode(message: Struct, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + Object.entries(message.fields).forEach(([key, value]) => { + if (value !== undefined) { + Struct_FieldsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).ldelim(); + } + }); + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Struct { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseStruct(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + const entry1 = Struct_FieldsEntry.decode(reader, reader.uint32()); + if (entry1.value !== undefined) { + message.fields[entry1.key] = entry1.value; + } + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Struct { + return { + fields: isObject(object.fields) + ? Object.entries(object.fields).reduce<{ [key: string]: any | undefined }>((acc, [key, value]) => { + acc[key] = value as any | undefined; + return acc; + }, {}) + : {}, + }; + }, + + toJSON(message: Struct): unknown { + const obj: any = {}; + obj.fields = {}; + if (message.fields) { + Object.entries(message.fields).forEach(([k, v]) => { + obj.fields[k] = v; + }); + } + return obj; + }, + + fromPartial, I>>(object: I): Struct { + const message = createBaseStruct(); + message.fields = Object.entries(object.fields ?? {}).reduce<{ [key: string]: any | undefined }>( + (acc, [key, value]) => { + if (value !== undefined) { + acc[key] = value; + } + return acc; + }, + {} + ); + return message; + }, + + wrap(object: { [key: string]: any } | undefined): Struct { + const struct = createBaseStruct(); + if (object !== undefined) { + Object.keys(object).forEach((key) => { + struct.fields[key] = object[key]; + }); + } + return struct; + }, + + unwrap(message: Struct): { [key: string]: any } { + const object: { [key: string]: any } = {}; + Object.keys(message.fields).forEach((key) => { + object[key] = message.fields[key]; + }); + return object; + }, +}; + +function createBaseStruct_FieldsEntry(): Struct_FieldsEntry { + return { key: '', value: undefined }; +} + +export const Struct_FieldsEntry = { + encode(message: Struct_FieldsEntry, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.key !== '') { + writer.uint32(10).string(message.key); + } + if (message.value !== undefined) { + Value.encode(Value.wrap(message.value), writer.uint32(18).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Struct_FieldsEntry { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseStruct_FieldsEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.key = reader.string(); + break; + case 2: + message.value = Value.unwrap(Value.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Struct_FieldsEntry { + return { + key: isSet(object.key) ? String(object.key) : '', + value: isSet(object?.value) ? object.value : undefined, + }; + }, + + toJSON(message: Struct_FieldsEntry): unknown { + const obj: any = {}; + message.key !== undefined && (obj.key = message.key); + message.value !== undefined && (obj.value = message.value); + return obj; + }, + + fromPartial, I>>(object: I): Struct_FieldsEntry { + const message = createBaseStruct_FieldsEntry(); + message.key = object.key ?? ''; + message.value = object.value ?? undefined; + return message; + }, +}; + +function createBaseValue(): Value { + return { + null_value: undefined, + number_value: undefined, + string_value: undefined, + bool_value: undefined, + struct_value: undefined, + list_value: undefined, + }; +} + +export const Value = { + encode(message: Value, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.null_value !== undefined) { + writer.uint32(8).int32(message.null_value); + } + if (message.number_value !== undefined) { + writer.uint32(17).double(message.number_value); + } + if (message.string_value !== undefined) { + writer.uint32(26).string(message.string_value); + } + if (message.bool_value !== undefined) { + writer.uint32(32).bool(message.bool_value); + } + if (message.struct_value !== undefined) { + Struct.encode(Struct.wrap(message.struct_value), writer.uint32(42).fork()).ldelim(); + } + if (message.list_value !== undefined) { + ListValue.encode(ListValue.wrap(message.list_value), writer.uint32(50).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Value { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.null_value = reader.int32() as any; + break; + case 2: + message.number_value = reader.double(); + break; + case 3: + message.string_value = reader.string(); + break; + case 4: + message.bool_value = reader.bool(); + break; + case 5: + message.struct_value = Struct.unwrap(Struct.decode(reader, reader.uint32())); + break; + case 6: + message.list_value = ListValue.unwrap(ListValue.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Value { + return { + null_value: isSet(object.null_value) ? nullValueFromJSON(object.null_value) : undefined, + number_value: isSet(object.number_value) ? Number(object.number_value) : undefined, + string_value: isSet(object.string_value) ? String(object.string_value) : undefined, + bool_value: isSet(object.bool_value) ? Boolean(object.bool_value) : undefined, + struct_value: isObject(object.struct_value) ? object.struct_value : undefined, + list_value: Array.isArray(object.list_value) ? [...object.list_value] : undefined, + }; + }, + + toJSON(message: Value): unknown { + const obj: any = {}; + message.null_value !== undefined && + (obj.null_value = message.null_value !== undefined ? nullValueToJSON(message.null_value) : undefined); + message.number_value !== undefined && (obj.number_value = message.number_value); + message.string_value !== undefined && (obj.string_value = message.string_value); + message.bool_value !== undefined && (obj.bool_value = message.bool_value); + message.struct_value !== undefined && (obj.struct_value = message.struct_value); + message.list_value !== undefined && (obj.list_value = message.list_value); + return obj; + }, + + fromPartial, I>>(object: I): Value { + const message = createBaseValue(); + message.null_value = object.null_value ?? undefined; + message.number_value = object.number_value ?? undefined; + message.string_value = object.string_value ?? undefined; + message.bool_value = object.bool_value ?? undefined; + message.struct_value = object.struct_value ?? undefined; + message.list_value = object.list_value ?? undefined; + return message; + }, + + wrap(value: any): Value { + const result = createBaseValue(); + + if (value === null) { + result.null_value = NullValue.NULL_VALUE; + } else if (typeof value === 'boolean') { + result.bool_value = value; + } else if (typeof value === 'number') { + result.number_value = value; + } else if (typeof value === 'string') { + result.string_value = value; + } else if (Array.isArray(value)) { + result.list_value = value; + } else if (typeof value === 'object') { + result.struct_value = value; + } else if (typeof value !== 'undefined') { + throw new Error('Unsupported any value type: ' + typeof value); + } + + return result; + }, + + unwrap(message: Value): string | number | boolean | Object | null | Array | undefined { + if (message?.string_value !== undefined) { + return message.string_value; + } else if (message?.number_value !== undefined) { + return message.number_value; + } else if (message?.bool_value !== undefined) { + return message.bool_value; + } else if (message?.struct_value !== undefined) { + return message.struct_value; + } else if (message?.list_value !== undefined) { + return message.list_value; + } else if (message?.null_value !== undefined) { + return null; + } + return undefined; + }, +}; + +function createBaseListValue(): ListValue { + return { values: [] }; +} + +export const ListValue = { + encode(message: ListValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + for (const v of message.values) { + Value.encode(Value.wrap(v!), writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): ListValue { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseListValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.values.push(Value.unwrap(Value.decode(reader, reader.uint32()))); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): ListValue { + return { + values: Array.isArray(object?.values) ? [...object.values] : [], + }; + }, + + toJSON(message: ListValue): unknown { + const obj: any = {}; + if (message.values) { + obj.values = message.values.map((e) => e); + } else { + obj.values = []; + } + return obj; + }, + + fromPartial, I>>(object: I): ListValue { + const message = createBaseListValue(); + message.values = object.values?.map((e) => e) || []; + return message; + }, + + wrap(value: Array | undefined): ListValue { + const result = createBaseListValue(); + + result.values = value ?? []; + + return result; + }, + + unwrap(message: ListValue): Array { + return message.values; + }, +}; + +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 } & Record>, never>; + +// 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 isObject(value: any): boolean { + return typeof value === 'object' && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} diff --git a/integration/simple-snake/simple-snake-test.ts b/integration/simple-snake/simple-snake-test.ts index f697f6356..6d8482dc9 100644 --- a/integration/simple-snake/simple-snake-test.ts +++ b/integration/simple-snake/simple-snake-test.ts @@ -1,4 +1,4 @@ -import { Child_Type, Simple, StateEnum } from './simple'; +import { Child_Type, Simple, StateEnum, SimpleStruct } from './simple'; const jan1 = new Date('1970-01-01T00:00:00.000Z'); @@ -18,4 +18,13 @@ describe('simple', () => { }; expect(simple.name).toEqual('asdf'); }); + + it('struct snake case', () => { + const simple: SimpleStruct = { + simple_struct: { + any: 'any' + } + } + expect(simple.simple_struct!['any']).toEqual('any') + }) }); diff --git a/integration/simple-snake/simple.bin b/integration/simple-snake/simple.bin index d6a2033aed6652e29d11a35799c6e4c716c2ab34..8b9d6a26408bb70259fb5e43615d00ed453673e9 100644 GIT binary patch delta 6271 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 delta 3563 zcmYjTOH))w6u!4_-^cVFVCK$?K_0_H9tIc{N=%8yC}2b&B`J|aQeuRNB`=YOm8#U; zCEHZZ56CW?ERvKftFp=>e6HH{C@6zuL=?=oVTr>g&%7T6)9IFUf^`7 zcdioBNo3yXYW=-1?tb6;Z(-SOv~J(Kp5~)=Raa6v!b!Y#k#yx7E6?_}8{fX%-rZ6v zuY5B3WQ#K70_EB=bUL3omV(ku)h=fgEKq&i+2U-$kL3-qgAPr3>UP)A$CP6ES zEFKA3DPK%8BY359g?Y%MEQZ+RL!~UT3i(he$A!!Wm2$B!Ll7ws46+CuD>k_RA{8qV z-~$ycl2X+Js8otsoB>oS^)6Nk6R#?I_yZwSs#Yb0N;NKKHi%S{&J01MdZC*|qQtA& zd?JX{GLfc;5N9neGcSTlt&$}aL8XR-OwV$OS8x4ue=@C$4tCGMyB6g9w@6Bt=Ceoidzu3TTTd9PHWiSKhO<`|RJ#fdgt=G7=NN;N_F{}O zf7ttEo3+!Y`ebyD;oleMtvg^t=B=4#t|7y7Om-BF#>b^t26*ZKQ0)P|8t54ym;<~U zK*)T6$Id0uL19J&0QDUdfk{_Te1k}r)(tk$29XR3=A$gb&Lv$ipTvj#b_&DSB^eRz zL?PfNsW&2W8AQM%`8M_hZPc3RQ=>w%BOMW=VZ@FAV`c;(N%4*epB)9+qMUA`NaVP4 z+cc59#&L$kDwR@DZ6>%j0I1Cb9~(gMoZ!*`A;$?WjsDamF9iTfGifq|BE>t|VYUDW zv`O9qK`}LXk%hP{z-#g*!vjWX7m?)}i^17c1 zcvP@!`I_obk+D;NGeK1qR4)4iAgKZwIH=cB1&08KNHIKHl4ZL|YokEm}yzhK&LZpl1eq@ekT*8UB zC`L2|0E4i|hcyr!7kdZTmQoyx7l(BilIrWRq-)51^{V27G}zT$W}Ft0RrtYHzuHYUKgg<0HCdl66=%XdO0(} zH~Muo!bCoCzBb{9aC;K<>M%kIe}fwh0KE;49te&b71L-S$Zep}7}Egz^3-{zq!W)Z^ruEB?P_A{s|pkl*s4Kwh50O2G4o>A_{Md69hoB zw)pf1g5y?BUsnRPLbR$%K<=cSES}q3kc6$)&qjxF7zl2MV;E?OAP?LJ)S`z zvhgz$2(&%E)D$&;-_itV`<6zM`$S7|G{FyrP0gv$bODi?#R;U z;d*3gc(}f?w9ropW}l;3e`9$ecyBBZZ`EVI>XnG_xnuL9LG@?`kCnOUfj~RvC%Y1O zoSul9UO52JPArW^?Ig9l9C#U?6V<6B@tDQ`X6YtE@ bV$jYkEe7q((qhogs-542!Qs)t@xj#pQ90Sm diff --git a/integration/simple-snake/simple.proto b/integration/simple-snake/simple.proto index b7928e59a..e5b6ef747 100644 --- a/integration/simple-snake/simple.proto +++ b/integration/simple-snake/simple.proto @@ -3,10 +3,11 @@ syntax = "proto3"; import "google/protobuf/wrappers.proto"; import "google/protobuf/timestamp.proto"; +import "google/protobuf/struct.proto"; import "import_dir/thing.proto"; package simple; -// This comment is seperated by a blank non-comment line, and will detatch from +// This comment is seperated by a blank non-comment line, and will detatch from // the following comment on the message Simple. /** Example comment on the Simple message */ @@ -119,3 +120,7 @@ message Numbers { sfixed32 sfixed32 = 11; sfixed64 sfixed64 = 12; } + +message SimpleStruct { + google.protobuf.Struct simple_struct = 1; +} diff --git a/integration/simple-snake/simple.ts b/integration/simple-snake/simple.ts index ed04acc4f..52811afca 100644 --- a/integration/simple-snake/simple.ts +++ b/integration/simple-snake/simple.ts @@ -4,6 +4,7 @@ import * as _m0 from 'protobufjs/minimal'; import { Timestamp } from './google/protobuf/timestamp'; import { ImportedThing } from './import_dir/thing'; import { StringValue, Int32Value, BoolValue } from './google/protobuf/wrappers'; +import { Struct } from './google/protobuf/struct'; export const protobufPackage = 'simple'; @@ -238,6 +239,10 @@ export interface Numbers { sfixed64: number; } +export interface SimpleStruct { + simple_struct: { [key: string]: any } | undefined; +} + function createBaseSimple(): Simple { return { name: '', @@ -1555,6 +1560,55 @@ export const Numbers = { }, }; +function createBaseSimpleStruct(): SimpleStruct { + return { simple_struct: undefined }; +} + +export const SimpleStruct = { + encode(message: SimpleStruct, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.simple_struct !== undefined) { + Struct.encode(Struct.wrap(message.simple_struct), writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): SimpleStruct { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseSimpleStruct(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.simple_struct = Struct.unwrap(Struct.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): SimpleStruct { + return { + simple_struct: isObject(object.simple_struct) ? object.simple_struct : undefined, + }; + }, + + toJSON(message: SimpleStruct): unknown { + const obj: any = {}; + message.simple_struct !== undefined && (obj.simple_struct = message.simple_struct); + return obj; + }, + + fromPartial, I>>(object: I): SimpleStruct { + const message = createBaseSimpleStruct(); + message.simple_struct = object.simple_struct ?? undefined; + return message; + }, +}; + export interface PingService { ping(request: PingRequest): Promise; } diff --git a/src/main.ts b/src/main.ts index a9ed9eed5..a04303fa2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -173,8 +173,16 @@ export function generateFile(ctx: Context, fileDesc: FileDescriptorProto): [stri staticMembers.push(generateFromPartial(ctx, fullName, message)); } - staticMembers.push(...generateWrap(ctx, fullTypeName)); - staticMembers.push(...generateUnwrap(ctx, fullTypeName)); + const structFieldNames = { + nullValue: maybeSnakeToCamel('null_value', ctx.options), + numberValue: maybeSnakeToCamel('number_value', ctx.options), + stringValue: maybeSnakeToCamel('string_value', ctx.options), + boolValue: maybeSnakeToCamel('bool_value', ctx.options), + structValue: maybeSnakeToCamel('struct_value', ctx.options), + listValue: maybeSnakeToCamel('list_value', ctx.options), + }; + staticMembers.push(...generateWrap(ctx, fullTypeName, structFieldNames)); + staticMembers.push(...generateUnwrap(ctx, fullTypeName, structFieldNames)); chunks.push(code` export const ${def(fullName)} = { @@ -1591,7 +1599,16 @@ function generateFromPartial(ctx: Context, fullName: string, messageDesc: Descri return joinCode(chunks, { on: '\n' }); } -function generateWrap(ctx: Context, fullProtoTypeName: string): Code[] { +type StructFieldNames = { + nullValue: string; + numberValue: string; + stringValue: string; + boolValue: string; + structValue: string; + listValue: string; +}; + +function generateWrap(ctx: Context, fullProtoTypeName: string, fieldNames: StructFieldNames): Code[] { const chunks: Code[] = []; if (isStructTypeName(fullProtoTypeName)) { chunks.push(code`wrap(object: {[key: string]: any} | undefined): Struct { @@ -1611,17 +1628,17 @@ function generateWrap(ctx: Context, fullProtoTypeName: string): Code[] { const result = createBaseValue(); if (value === null) { - result.kind = {$case: 'nullValue', nullValue: NullValue.NULL_VALUE}; + result.kind = {$case: '${fieldNames.nullValue}', ${fieldNames.nullValue}: NullValue.NULL_VALUE}; } else if (typeof value === 'boolean') { - result.kind = {$case: 'boolValue', boolValue: value}; + result.kind = {$case: '${fieldNames.boolValue}', ${fieldNames.boolValue}: value}; } else if (typeof value === 'number') { - result.kind = {$case: 'numberValue', numberValue: value}; + result.kind = {$case: '${fieldNames.numberValue}', ${fieldNames.numberValue}: value}; } else if (typeof value === 'string') { - result.kind = {$case: 'stringValue', stringValue: value}; + result.kind = {$case: '${fieldNames.stringValue}', ${fieldNames.stringValue}: value}; } else if (Array.isArray(value)) { - result.kind = {$case: 'listValue', listValue: value}; + result.kind = {$case: '${fieldNames.listValue}', ${fieldNames.listValue}: value}; } else if (typeof value === 'object') { - result.kind = {$case: 'structValue', structValue: value}; + result.kind = {$case: '${fieldNames.structValue}', ${fieldNames.structValue}: value}; } else if (typeof value !== 'undefined') { throw new Error('Unsupported any value type: ' + typeof value); } @@ -1633,17 +1650,17 @@ function generateWrap(ctx: Context, fullProtoTypeName: string): Code[] { const result = createBaseValue(); if (value === null) { - result.nullValue = NullValue.NULL_VALUE; + result.${fieldNames.nullValue} = NullValue.NULL_VALUE; } else if (typeof value === 'boolean') { - result.boolValue = value; + result.${fieldNames.boolValue} = value; } else if (typeof value === 'number') { - result.numberValue = value; + result.${fieldNames.numberValue} = value; } else if (typeof value === 'string') { - result.stringValue = value; + result.${fieldNames.stringValue} = value; } else if (Array.isArray(value)) { - result.listValue = value; + result.${fieldNames.listValue} = value; } else if (typeof value === 'object') { - result.structValue = value; + result.${fieldNames.structValue} = value; } else if (typeof value !== 'undefined') { throw new Error('Unsupported any value type: ' + typeof value); } @@ -1672,7 +1689,7 @@ function generateWrap(ctx: Context, fullProtoTypeName: string): Code[] { return chunks; } -function generateUnwrap(ctx: Context, fullProtoTypeName: string): Code[] { +function generateUnwrap(ctx: Context, fullProtoTypeName: string, fieldNames: StructFieldNames): Code[] { const chunks: Code[] = []; if (isStructTypeName(fullProtoTypeName)) { chunks.push(code`unwrap(message: Struct): {[key: string]: any} { @@ -1687,35 +1704,35 @@ function generateUnwrap(ctx: Context, fullProtoTypeName: string): Code[] { if (isAnyValueTypeName(fullProtoTypeName)) { if (ctx.options.oneof === OneofOption.UNIONS) { chunks.push(code`unwrap(message: Value): string | number | boolean | Object | null | Array | undefined { - if (message.kind?.$case === 'nullValue') { + if (message.kind?.$case === '${fieldNames.nullValue}') { return null; - } else if (message.kind?.$case === 'numberValue') { - return message.kind?.numberValue; - } else if (message.kind?.$case === 'stringValue') { - return message.kind?.stringValue; - } else if (message.kind?.$case === 'boolValue') { - return message.kind?.boolValue; - } else if (message.kind?.$case === 'structValue') { - return message.kind?.structValue; - } else if (message.kind?.$case === 'listValue') { - return message.kind?.listValue; + } else if (message.kind?.$case === '${fieldNames.numberValue}') { + return message.kind?.${fieldNames.numberValue}; + } else if (message.kind?.$case === '${fieldNames.stringValue}') { + return message.kind?.${fieldNames.stringValue}; + } else if (message.kind?.$case === '${fieldNames.boolValue}') { + return message.kind?.${fieldNames.boolValue}; + } else if (message.kind?.$case === '${fieldNames.structValue}') { + return message.kind?.${fieldNames.structValue}; + } else if (message.kind?.$case === '${fieldNames.listValue}') { + return message.kind?.${fieldNames.listValue}; } else { return undefined; } }`); } else { chunks.push(code`unwrap(message: Value): string | number | boolean | Object | null | Array | undefined { - if (message?.stringValue !== undefined) { - return message.stringValue; - } else if (message?.numberValue !== undefined) { - return message.numberValue; - } else if (message?.boolValue !== undefined) { - return message.boolValue; - } else if (message?.structValue !== undefined) { - return message.structValue; - } else if (message?.listValue !== undefined) { - return message.listValue; - } else if (message?.nullValue !== undefined) { + if (message?.${fieldNames.stringValue} !== undefined) { + return message.${fieldNames.stringValue}; + } else if (message?.${fieldNames.numberValue} !== undefined) { + return message.${fieldNames.numberValue}; + } else if (message?.${fieldNames.boolValue} !== undefined) { + return message.${fieldNames.boolValue}; + } else if (message?.${fieldNames.structValue} !== undefined) { + return message.${fieldNames.structValue}; + } else if (message?.${fieldNames.listValue} !== undefined) { + return message.${fieldNames.listValue}; + } else if (message?.${fieldNames.nullValue} !== undefined) { return null; } return undefined;