diff --git a/integration/oneof-unions/oneof-unions-test.ts b/integration/oneof-unions/oneof-unions-test.ts index 6cdc2f11d..65ee9b6ed 100644 --- a/integration/oneof-unions/oneof-unions-test.ts +++ b/integration/oneof-unions/oneof-unions-test.ts @@ -3,12 +3,22 @@ import { PleaseChoose } from './oneof'; describe('oneof=unions', () => { it('generates types correctly', () => { - const alice: PleaseChoose = { name: 'Alice', age: 42 }; - const bob: PleaseChoose = { name: 'Bob', age: 42, choice: { $case: 'aNumber', aNumber: 132 } }; + const alice: PleaseChoose = { + name: 'Alice', + age: 42, + signature: new Uint8Array([0xab, 0xcd]), + }; + const bob: PleaseChoose = { + name: 'Bob', + age: 42, + choice: { $case: 'aNumber', aNumber: 132 }, + signature: new Uint8Array([0xab, 0xcd]), + }; const charlie: PleaseChoose = { name: 'Charlie', age: 42, choice: { $case: 'aMessage', aMessage: { name: 'charlie' } }, + signature: new Uint8Array([0xab, 0xcd]), }; }); @@ -27,6 +37,7 @@ describe('oneof=unions', () => { age: 37, choice: { $case: 'aBool', aBool: true }, eitherOr: { $case: 'or', or: 'perhaps not' }, + signature: new Uint8Array(), }); }); @@ -36,6 +47,7 @@ describe('oneof=unions', () => { age: 37, choice: { $case: 'aBool', aBool: true }, eitherOr: { $case: 'or', or: 'perhaps not' }, + signature: new Uint8Array([0xab, 0xcd]), }).finish(); let decoded = pbjs.PleaseChoose.decode(encoded); expect(decoded).toEqual({ @@ -43,6 +55,7 @@ describe('oneof=unions', () => { aBool: true, age: 37, or: 'perhaps not', + signature: Buffer.from([0xab, 0xcd]), }); }); @@ -51,6 +64,7 @@ describe('oneof=unions', () => { expect(empty).toEqual({ name: '', age: 0, + signature: new Uint8Array(), }); let partial = PleaseChoose.fromPartial({ @@ -58,12 +72,14 @@ describe('oneof=unions', () => { age: 37, choice: { $case: 'aBool', aBool: true }, eitherOr: { $case: 'or', or: 'perhaps not' }, + signature: new Uint8Array([0xab, 0xcd]), }); expect(partial).toEqual({ name: 'Debbie', age: 37, choice: { $case: 'aBool', aBool: true }, eitherOr: { $case: 'or', or: 'perhaps not' }, + signature: new Uint8Array([0xab, 0xcd]), }); }); @@ -73,6 +89,7 @@ describe('oneof=unions', () => { age: 37, choice: { $case: 'aBool', aBool: true }, eitherOr: { $case: 'or', or: 'perhaps not' }, + signature: new Uint8Array([0xab, 0xcd]), }; let pbjsJson = pbjs.PleaseChoose.decode(PleaseChoose.encode(debbie).finish()).toJSON(); let json = PleaseChoose.toJSON(debbie); @@ -81,13 +98,14 @@ describe('oneof=unions', () => { it('fromJSON', () => { let empty = PleaseChoose.fromJSON({}); - expect(empty).toEqual({ age: 0, name: '' }); + expect(empty).toEqual({ age: 0, name: '', signature: new Uint8Array() }); let debbie: PleaseChoose = { name: 'Debbie', age: 37, choice: { $case: 'aBool', aBool: true }, eitherOr: { $case: 'or', or: 'perhaps not' }, + signature: new Uint8Array([0xab, 0xcd]), }; let pbjsJson = pbjs.PleaseChoose.decode(PleaseChoose.encode(debbie).finish()).toJSON(); let fromJson = PleaseChoose.fromJSON(pbjsJson); @@ -99,6 +117,7 @@ describe('oneof=unions', () => { name: 'Debbie', age: 37, choice: { $case: 'aNumber', aNumber: 42 }, + signature: Buffer.from([0xab, 0xcd]), }; let encoded = PleaseChoose.encode(obj).finish(); let decoded = PleaseChoose.decode(encoded); diff --git a/integration/oneof-unions/oneof.bin b/integration/oneof-unions/oneof.bin index 45b7fdb4f..365dbb4d0 100644 Binary files a/integration/oneof-unions/oneof.bin and b/integration/oneof-unions/oneof.bin differ diff --git a/integration/oneof-unions/oneof.proto b/integration/oneof-unions/oneof.proto index cf0a4fe45..1f8a35697 100644 --- a/integration/oneof-unions/oneof.proto +++ b/integration/oneof-unions/oneof.proto @@ -46,6 +46,7 @@ message PleaseChoose { string third_option = 9; } + bytes signature = 12; } /** For testing proto3's field presence feature. */ diff --git a/integration/oneof-unions/oneof.ts b/integration/oneof-unions/oneof.ts index fd55ba7be..4f419f7fd 100644 --- a/integration/oneof-unions/oneof.ts +++ b/integration/oneof-unions/oneof.ts @@ -18,6 +18,7 @@ export interface PleaseChoose { | { $case: 'either'; either: string } | { $case: 'or'; or: string } | { $case: 'thirdOption'; thirdOption: string }; + signature: Uint8Array; } export enum PleaseChoose_StateEnum { @@ -105,6 +106,9 @@ export const PleaseChoose = { if (message.eitherOr?.$case === 'thirdOption') { writer.uint32(74).string(message.eitherOr.thirdOption); } + if (message.signature.length !== 0) { + writer.uint32(98).bytes(message.signature); + } return writer; }, @@ -112,6 +116,7 @@ export const PleaseChoose = { const reader = input instanceof Reader ? input : new Reader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = { ...basePleaseChoose } as PleaseChoose; + message.signature = new Uint8Array(); while (reader.pos < end) { const tag = reader.uint32(); switch (tag >>> 3) { @@ -148,6 +153,9 @@ export const PleaseChoose = { case 9: message.eitherOr = { $case: 'thirdOption', thirdOption: reader.string() }; break; + case 12: + message.signature = reader.bytes(); + break; default: reader.skipType(tag & 7); break; @@ -158,6 +166,7 @@ export const PleaseChoose = { fromJSON(object: any): PleaseChoose { const message = { ...basePleaseChoose } as PleaseChoose; + message.signature = new Uint8Array(); if (object.name !== undefined && object.name !== null) { message.name = String(object.name); } @@ -191,6 +200,9 @@ export const PleaseChoose = { if (object.thirdOption !== undefined && object.thirdOption !== null) { message.eitherOr = { $case: 'thirdOption', thirdOption: String(object.thirdOption) }; } + if (object.signature !== undefined && object.signature !== null) { + message.signature = bytesFromBase64(object.signature); + } return message; }, @@ -212,6 +224,8 @@ export const PleaseChoose = { message.eitherOr?.$case === 'either' && (obj.either = message.eitherOr?.either); message.eitherOr?.$case === 'or' && (obj.or = message.eitherOr?.or); message.eitherOr?.$case === 'thirdOption' && (obj.thirdOption = message.eitherOr?.thirdOption); + message.signature !== undefined && + (obj.signature = base64FromBytes(message.signature !== undefined ? message.signature : new Uint8Array())); return obj; }, @@ -219,6 +233,8 @@ export const PleaseChoose = { const message = { ...basePleaseChoose } as PleaseChoose; if (object.name !== undefined && object.name !== null) { message.name = object.name; + } else { + message.name = ''; } if (object.choice?.$case === 'aNumber' && object.choice?.aNumber !== undefined && object.choice?.aNumber !== null) { message.choice = { $case: 'aNumber', aNumber: object.choice.aNumber }; @@ -248,6 +264,8 @@ export const PleaseChoose = { } if (object.age !== undefined && object.age !== null) { message.age = object.age; + } else { + message.age = 0; } if ( object.eitherOr?.$case === 'either' && @@ -266,6 +284,11 @@ export const PleaseChoose = { ) { message.eitherOr = { $case: 'thirdOption', thirdOption: object.eitherOr.thirdOption }; } + if (object.signature !== undefined && object.signature !== null) { + message.signature = object.signature; + } else { + message.signature = new Uint8Array(); + } return message; }, }; @@ -316,6 +339,8 @@ export const PleaseChoose_Submessage = { const message = { ...basePleaseChoose_Submessage } as PleaseChoose_Submessage; if (object.name !== undefined && object.name !== null) { message.name = object.name; + } else { + message.name = ''; } return message; }, @@ -377,9 +402,13 @@ export const SimpleButOptional = { const message = { ...baseSimpleButOptional } as SimpleButOptional; if (object.name !== undefined && object.name !== null) { message.name = object.name; + } else { + message.name = undefined; } if (object.age !== undefined && object.age !== null) { message.age = object.age; + } else { + message.age = undefined; } return message; }, diff --git a/src/main.ts b/src/main.ts index f99a46259..02faa1390 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1222,7 +1222,7 @@ function generateFromPartial(ctx: Context, fullName: string, messageDesc: Descri } } - if (!isRepeated(field) && options.oneof !== OneofOption.UNIONS) { + if (!isRepeated(field) && !isWithinOneOfThatShouldBeUnion(options, field)) { chunks.push(code`} else {`); const v = isWithinOneOf(field) ? 'undefined' : defaultValue(ctx, field); chunks.push(code`message.${fieldName} = ${v}`);