diff --git a/vertx-codegen-protobuf/src/converters/generated/dataobjects.proto b/vertx-codegen-protobuf/src/converters/generated/dataobjects.proto index b210ad988..a5fc0eb34 100644 --- a/vertx-codegen-protobuf/src/converters/generated/dataobjects.proto +++ b/vertx-codegen-protobuf/src/converters/generated/dataobjects.proto @@ -43,6 +43,13 @@ message RecursiveItem { RecursiveItem childC = 4; } +message SimplePojo { + int32 integerField = 1; + int64 longField = 2; + bool booleanField = 3; + string stringField = 4; +} + message User { string userName = 1; int32 age = 2; diff --git a/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/AddressProtoConverter.java b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/AddressProtoConverter.java index 863756ed3..3e210a732 100644 --- a/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/AddressProtoConverter.java +++ b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/AddressProtoConverter.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Arrays; +import io.vertx.codegen.protobuf.ProtobufEncodingMode; import io.vertx.core.json.JsonObject; import io.vertx.codegen.protobuf.utils.ExpandableIntArray; import io.vertx.codegen.protobuf.converters.*; @@ -17,6 +18,16 @@ public class AddressProtoConverter { public static void fromProto(CodedInputStream input, Address obj) throws IOException { + fromProto(input, obj, ProtobufEncodingMode.VERTX); + } + + public static void fromProto(CodedInputStream input, Address obj, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; + if (compatibleMode) { + obj.setName(""); + obj.setLongitude(0f); + obj.setLatitude(0f); + } int tag; while ((tag = input.readTag()) != 0) { switch (tag) { @@ -33,36 +44,57 @@ public static void fromProto(CodedInputStream input, Address obj) throws IOExcep break; } } - } + } // while loop } public static void toProto(Address obj, CodedOutputStream output) throws IOException { + toProto(obj, output, ProtobufEncodingMode.VERTX); + } + + public static void toProto(Address obj, CodedOutputStream output, ProtobufEncodingMode encodingMode) throws IOException { ExpandableIntArray cache = new ExpandableIntArray(16); - AddressProtoConverter.computeSize(obj, cache, 0); - AddressProtoConverter.toProto(obj, output, cache, 0); + AddressProtoConverter.computeSize(obj, cache, 0, encodingMode); + AddressProtoConverter.toProto(obj, output, cache, 0, encodingMode); } - public static int toProto(Address obj, CodedOutputStream output, ExpandableIntArray cache, int index) throws IOException { + static int toProto(Address obj, CodedOutputStream output, ExpandableIntArray cache, int index, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; index = index + 1; - if (obj.getName() != null) { + // name + if (compatibleMode && obj.getName() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getName() != null) || (compatibleMode && !obj.getName().isEmpty())) { output.writeString(1, obj.getName()); } - if (obj.getLongitude() != null) { + // longitude + if (compatibleMode && obj.getLongitude() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getLongitude() != null) || (compatibleMode && obj.getLongitude() != 0f)) { output.writeFloat(2, obj.getLongitude()); } - if (obj.getLatitude() != null) { + // latitude + if (compatibleMode && obj.getLatitude() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getLatitude() != null) || (compatibleMode && obj.getLatitude() != 0f)) { output.writeFloat(3, obj.getLatitude()); } return index; } public static int computeSize(Address obj) { + return computeSize(obj, ProtobufEncodingMode.VERTX); + } + + public static int computeSize(Address obj, ProtobufEncodingMode encodingMode) { ExpandableIntArray cache = new ExpandableIntArray(16); - AddressProtoConverter.computeSize(obj, cache, 0); + AddressProtoConverter.computeSize(obj, cache, 0, encodingMode); return cache.get(0); } - public static int computeSize(Address obj, ExpandableIntArray cache, final int baseIndex) { + static int computeSize(Address obj, ExpandableIntArray cache, final int baseIndex, ProtobufEncodingMode encodingMode) { int size = 0; int index = baseIndex + 1; if (obj.getName() != null) { diff --git a/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/BookProtoConverter.java b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/BookProtoConverter.java index 0b617d0c9..cdfefae5f 100644 --- a/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/BookProtoConverter.java +++ b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/BookProtoConverter.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Arrays; +import io.vertx.codegen.protobuf.ProtobufEncodingMode; import io.vertx.core.json.JsonObject; import io.vertx.codegen.protobuf.utils.ExpandableIntArray; import io.vertx.codegen.protobuf.converters.*; @@ -17,6 +18,17 @@ public class BookProtoConverter { public static void fromProto(CodedInputStream input, Book obj) throws IOException { + fromProto(input, obj, ProtobufEncodingMode.VERTX); + } + + public static void fromProto(CodedInputStream input, Book obj, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; + if (compatibleMode) { + obj.setName(""); + obj.setAuthor(""); + obj.setIsbn(""); + obj.setGenre(""); + } int tag; while ((tag = input.readTag()) != 0) { switch (tag) { @@ -37,39 +49,64 @@ public static void fromProto(CodedInputStream input, Book obj) throws IOExceptio break; } } - } + } // while loop } public static void toProto(Book obj, CodedOutputStream output) throws IOException { + toProto(obj, output, ProtobufEncodingMode.VERTX); + } + + public static void toProto(Book obj, CodedOutputStream output, ProtobufEncodingMode encodingMode) throws IOException { ExpandableIntArray cache = new ExpandableIntArray(16); - BookProtoConverter.computeSize(obj, cache, 0); - BookProtoConverter.toProto(obj, output, cache, 0); + BookProtoConverter.computeSize(obj, cache, 0, encodingMode); + BookProtoConverter.toProto(obj, output, cache, 0, encodingMode); } - public static int toProto(Book obj, CodedOutputStream output, ExpandableIntArray cache, int index) throws IOException { + static int toProto(Book obj, CodedOutputStream output, ExpandableIntArray cache, int index, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; index = index + 1; - if (obj.getName() != null) { + // name + if (compatibleMode && obj.getName() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getName() != null) || (compatibleMode && !obj.getName().isEmpty())) { output.writeString(1, obj.getName()); } - if (obj.getAuthor() != null) { + // author + if (compatibleMode && obj.getAuthor() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getAuthor() != null) || (compatibleMode && !obj.getAuthor().isEmpty())) { output.writeString(3, obj.getAuthor()); } - if (obj.getIsbn() != null) { + // isbn + if (compatibleMode && obj.getIsbn() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getIsbn() != null) || (compatibleMode && !obj.getIsbn().isEmpty())) { output.writeString(10, obj.getIsbn()); } - if (obj.getGenre() != null) { + // genre + if (compatibleMode && obj.getGenre() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getGenre() != null) || (compatibleMode && !obj.getGenre().isEmpty())) { output.writeString(20, obj.getGenre()); } return index; } public static int computeSize(Book obj) { + return computeSize(obj, ProtobufEncodingMode.VERTX); + } + + public static int computeSize(Book obj, ProtobufEncodingMode encodingMode) { ExpandableIntArray cache = new ExpandableIntArray(16); - BookProtoConverter.computeSize(obj, cache, 0); + BookProtoConverter.computeSize(obj, cache, 0, encodingMode); return cache.get(0); } - public static int computeSize(Book obj, ExpandableIntArray cache, final int baseIndex) { + static int computeSize(Book obj, ExpandableIntArray cache, final int baseIndex, ProtobufEncodingMode encodingMode) { int size = 0; int index = baseIndex + 1; if (obj.getName() != null) { diff --git a/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/PersonProtoConverter.java b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/PersonProtoConverter.java index 46002f198..6b752d547 100644 --- a/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/PersonProtoConverter.java +++ b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/PersonProtoConverter.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Arrays; +import io.vertx.codegen.protobuf.ProtobufEncodingMode; import io.vertx.core.json.JsonObject; import io.vertx.codegen.protobuf.utils.ExpandableIntArray; import io.vertx.codegen.protobuf.converters.*; @@ -17,6 +18,14 @@ public class PersonProtoConverter { public static void fromProto(CodedInputStream input, Person obj) throws IOException { + fromProto(input, obj, ProtobufEncodingMode.VERTX); + } + + public static void fromProto(CodedInputStream input, Person obj, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; + if (compatibleMode) { + obj.setName(""); + } int tag; while ((tag = input.readTag()) != 0) { switch (tag) { @@ -29,20 +38,30 @@ public static void fromProto(CodedInputStream input, Person obj) throws IOExcept break; } } - } + } // while loop } public static void toProto(Person obj, CodedOutputStream output) throws IOException { + toProto(obj, output, ProtobufEncodingMode.VERTX); + } + + public static void toProto(Person obj, CodedOutputStream output, ProtobufEncodingMode encodingMode) throws IOException { ExpandableIntArray cache = new ExpandableIntArray(16); - PersonProtoConverter.computeSize(obj, cache, 0); - PersonProtoConverter.toProto(obj, output, cache, 0); + PersonProtoConverter.computeSize(obj, cache, 0, encodingMode); + PersonProtoConverter.toProto(obj, output, cache, 0, encodingMode); } - public static int toProto(Person obj, CodedOutputStream output, ExpandableIntArray cache, int index) throws IOException { + static int toProto(Person obj, CodedOutputStream output, ExpandableIntArray cache, int index, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; index = index + 1; - if (obj.getName() != null) { + // name + if (compatibleMode && obj.getName() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getName() != null) || (compatibleMode && !obj.getName().isEmpty())) { output.writeString(2, obj.getName()); } + // age if (obj.getAge() != 0) { output.writeInt32(4, obj.getAge()); } @@ -50,12 +69,16 @@ public static int toProto(Person obj, CodedOutputStream output, ExpandableIntArr } public static int computeSize(Person obj) { + return computeSize(obj, ProtobufEncodingMode.VERTX); + } + + public static int computeSize(Person obj, ProtobufEncodingMode encodingMode) { ExpandableIntArray cache = new ExpandableIntArray(16); - PersonProtoConverter.computeSize(obj, cache, 0); + PersonProtoConverter.computeSize(obj, cache, 0, encodingMode); return cache.get(0); } - public static int computeSize(Person obj, ExpandableIntArray cache, final int baseIndex) { + static int computeSize(Person obj, ExpandableIntArray cache, final int baseIndex, ProtobufEncodingMode encodingMode) { int size = 0; int index = baseIndex + 1; if (obj.getName() != null) { diff --git a/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/RecursiveItemProtoConverter.java b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/RecursiveItemProtoConverter.java index 659e4273d..86be31240 100644 --- a/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/RecursiveItemProtoConverter.java +++ b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/RecursiveItemProtoConverter.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Arrays; +import io.vertx.codegen.protobuf.ProtobufEncodingMode; import io.vertx.core.json.JsonObject; import io.vertx.codegen.protobuf.utils.ExpandableIntArray; import io.vertx.codegen.protobuf.converters.*; @@ -17,6 +18,14 @@ public class RecursiveItemProtoConverter { public static void fromProto(CodedInputStream input, RecursiveItem obj) throws IOException { + fromProto(input, obj, ProtobufEncodingMode.VERTX); + } + + public static void fromProto(CodedInputStream input, RecursiveItem obj, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; + if (compatibleMode) { + obj.setId(""); + } int tag; while ((tag = input.readTag()) != 0) { switch (tag) { @@ -52,45 +61,61 @@ public static void fromProto(CodedInputStream input, RecursiveItem obj) throws I break; } } - } + } // while loop } public static void toProto(RecursiveItem obj, CodedOutputStream output) throws IOException { + toProto(obj, output, ProtobufEncodingMode.VERTX); + } + + public static void toProto(RecursiveItem obj, CodedOutputStream output, ProtobufEncodingMode encodingMode) throws IOException { ExpandableIntArray cache = new ExpandableIntArray(16); - RecursiveItemProtoConverter.computeSize(obj, cache, 0); - RecursiveItemProtoConverter.toProto(obj, output, cache, 0); + RecursiveItemProtoConverter.computeSize(obj, cache, 0, encodingMode); + RecursiveItemProtoConverter.toProto(obj, output, cache, 0, encodingMode); } - public static int toProto(RecursiveItem obj, CodedOutputStream output, ExpandableIntArray cache, int index) throws IOException { + static int toProto(RecursiveItem obj, CodedOutputStream output, ExpandableIntArray cache, int index, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; index = index + 1; - if (obj.getId() != null) { + // id + if (compatibleMode && obj.getId() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getId() != null) || (compatibleMode && !obj.getId().isEmpty())) { output.writeString(1, obj.getId()); } + // childA if (obj.getChildA() != null) { output.writeUInt32NoTag(18); output.writeUInt32NoTag(cache.get(index)); - index = RecursiveItemProtoConverter.toProto(obj.getChildA(), output, cache, index); + index = RecursiveItemProtoConverter.toProto(obj.getChildA(), output, cache, index, encodingMode); } + // childB if (obj.getChildB() != null) { output.writeUInt32NoTag(26); output.writeUInt32NoTag(cache.get(index)); - index = RecursiveItemProtoConverter.toProto(obj.getChildB(), output, cache, index); + index = RecursiveItemProtoConverter.toProto(obj.getChildB(), output, cache, index, encodingMode); } + // childC if (obj.getChildC() != null) { output.writeUInt32NoTag(34); output.writeUInt32NoTag(cache.get(index)); - index = RecursiveItemProtoConverter.toProto(obj.getChildC(), output, cache, index); + index = RecursiveItemProtoConverter.toProto(obj.getChildC(), output, cache, index, encodingMode); } return index; } public static int computeSize(RecursiveItem obj) { + return computeSize(obj, ProtobufEncodingMode.VERTX); + } + + public static int computeSize(RecursiveItem obj, ProtobufEncodingMode encodingMode) { ExpandableIntArray cache = new ExpandableIntArray(16); - RecursiveItemProtoConverter.computeSize(obj, cache, 0); + RecursiveItemProtoConverter.computeSize(obj, cache, 0, encodingMode); return cache.get(0); } - public static int computeSize(RecursiveItem obj, ExpandableIntArray cache, final int baseIndex) { + static int computeSize(RecursiveItem obj, ExpandableIntArray cache, final int baseIndex, ProtobufEncodingMode encodingMode) { int size = 0; int index = baseIndex + 1; if (obj.getId() != null) { @@ -99,7 +124,7 @@ public static int computeSize(RecursiveItem obj, ExpandableIntArray cache, final if (obj.getChildA() != null) { size += CodedOutputStream.computeUInt32SizeNoTag(18); int savedIndex = index; - index = RecursiveItemProtoConverter.computeSize(obj.getChildA(), cache, index); + index = RecursiveItemProtoConverter.computeSize(obj.getChildA(), cache, index, encodingMode); int dataSize = cache.get(savedIndex); size += CodedOutputStream.computeUInt32SizeNoTag(dataSize); size += dataSize; @@ -107,7 +132,7 @@ public static int computeSize(RecursiveItem obj, ExpandableIntArray cache, final if (obj.getChildB() != null) { size += CodedOutputStream.computeUInt32SizeNoTag(26); int savedIndex = index; - index = RecursiveItemProtoConverter.computeSize(obj.getChildB(), cache, index); + index = RecursiveItemProtoConverter.computeSize(obj.getChildB(), cache, index, encodingMode); int dataSize = cache.get(savedIndex); size += CodedOutputStream.computeUInt32SizeNoTag(dataSize); size += dataSize; @@ -115,7 +140,7 @@ public static int computeSize(RecursiveItem obj, ExpandableIntArray cache, final if (obj.getChildC() != null) { size += CodedOutputStream.computeUInt32SizeNoTag(34); int savedIndex = index; - index = RecursiveItemProtoConverter.computeSize(obj.getChildC(), cache, index); + index = RecursiveItemProtoConverter.computeSize(obj.getChildC(), cache, index, encodingMode); int dataSize = cache.get(savedIndex); size += CodedOutputStream.computeUInt32SizeNoTag(dataSize); size += dataSize; diff --git a/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/SimplePojoProtoConverter.java b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/SimplePojoProtoConverter.java new file mode 100644 index 000000000..decb01c7a --- /dev/null +++ b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/SimplePojoProtoConverter.java @@ -0,0 +1,128 @@ +package io.vertx.test.codegen.converter; + +import com.google.protobuf.CodedOutputStream; +import com.google.protobuf.CodedInputStream; +import java.io.IOException; +import java.time.Instant; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; +import java.util.Map; +import java.util.Arrays; +import io.vertx.codegen.protobuf.ProtobufEncodingMode; +import io.vertx.core.json.JsonObject; +import io.vertx.codegen.protobuf.utils.ExpandableIntArray; +import io.vertx.codegen.protobuf.converters.*; + +public class SimplePojoProtoConverter { + + public static void fromProto(CodedInputStream input, SimplePojo obj) throws IOException { + fromProto(input, obj, ProtobufEncodingMode.VERTX); + } + + public static void fromProto(CodedInputStream input, SimplePojo obj, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; + if (compatibleMode) { + obj.setIntegerField(0); + obj.setLongField(0L); + obj.setBooleanField(false); + obj.setStringField(""); + } + int tag; + while ((tag = input.readTag()) != 0) { + switch (tag) { + case 8: { + obj.setIntegerField(input.readInt32()); + break; + } + case 16: { + obj.setLongField(input.readInt64()); + break; + } + case 24: { + obj.setBooleanField(input.readBool()); + break; + } + case 34: { + obj.setStringField(input.readString()); + break; + } + } + } // while loop + } + + public static void toProto(SimplePojo obj, CodedOutputStream output) throws IOException { + toProto(obj, output, ProtobufEncodingMode.VERTX); + } + + public static void toProto(SimplePojo obj, CodedOutputStream output, ProtobufEncodingMode encodingMode) throws IOException { + ExpandableIntArray cache = new ExpandableIntArray(16); + SimplePojoProtoConverter.computeSize(obj, cache, 0, encodingMode); + SimplePojoProtoConverter.toProto(obj, output, cache, 0, encodingMode); + } + + static int toProto(SimplePojo obj, CodedOutputStream output, ExpandableIntArray cache, int index, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; + index = index + 1; + // integerField + if (compatibleMode && obj.getIntegerField() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getIntegerField() != null) || (compatibleMode && obj.getIntegerField() != 0)) { + output.writeInt32(1, obj.getIntegerField()); + } + // longField + if (compatibleMode && obj.getLongField() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getLongField() != null) || (compatibleMode && obj.getLongField() != 0L)) { + output.writeInt64(2, obj.getLongField()); + } + // booleanField + if (compatibleMode && obj.getBooleanField() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getBooleanField() != null) || (compatibleMode && !obj.getBooleanField())) { + output.writeBool(3, obj.getBooleanField()); + } + // stringField + if (compatibleMode && obj.getStringField() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getStringField() != null) || (compatibleMode && !obj.getStringField().isEmpty())) { + output.writeString(4, obj.getStringField()); + } + return index; + } + + public static int computeSize(SimplePojo obj) { + return computeSize(obj, ProtobufEncodingMode.VERTX); + } + + public static int computeSize(SimplePojo obj, ProtobufEncodingMode encodingMode) { + ExpandableIntArray cache = new ExpandableIntArray(16); + SimplePojoProtoConverter.computeSize(obj, cache, 0, encodingMode); + return cache.get(0); + } + + static int computeSize(SimplePojo obj, ExpandableIntArray cache, final int baseIndex, ProtobufEncodingMode encodingMode) { + int size = 0; + int index = baseIndex + 1; + if (obj.getIntegerField() != null) { + size += CodedOutputStream.computeInt32Size(1, obj.getIntegerField()); + } + if (obj.getLongField() != null) { + size += CodedOutputStream.computeInt64Size(2, obj.getLongField()); + } + if (obj.getBooleanField() != null) { + size += CodedOutputStream.computeBoolSize(3, obj.getBooleanField()); + } + if (obj.getStringField() != null) { + size += CodedOutputStream.computeStringSize(4, obj.getStringField()); + } + cache.set(baseIndex, size); + return index; + } + +} diff --git a/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/UserProtoConverter.java b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/UserProtoConverter.java index c1dd876e7..5eae5c42e 100644 --- a/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/UserProtoConverter.java +++ b/vertx-codegen-protobuf/src/converters/generated/io/vertx/test/codegen/converter/UserProtoConverter.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Arrays; +import io.vertx.codegen.protobuf.ProtobufEncodingMode; import io.vertx.core.json.JsonObject; import io.vertx.codegen.protobuf.utils.ExpandableIntArray; import io.vertx.codegen.protobuf.converters.*; @@ -17,6 +18,20 @@ public class UserProtoConverter { public static void fromProto(CodedInputStream input, User obj) throws IOException { + fromProto(input, obj, ProtobufEncodingMode.VERTX); + } + + public static void fromProto(CodedInputStream input, User obj, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; + if (compatibleMode) { + obj.setUserName(""); + obj.setAge(0); + obj.setDoubleField(0d); + obj.setFloatField(0f); + obj.setLongField(0L); + obj.setBoolField(false); + obj.setShortField((short)0); + } int tag; while ((tag = input.readTag()) != 0) { switch (tag) { @@ -271,23 +286,37 @@ public static void fromProto(CodedInputStream input, User obj) throws IOExceptio break; } } - } + } // while loop } public static void toProto(User obj, CodedOutputStream output) throws IOException { + toProto(obj, output, ProtobufEncodingMode.VERTX); + } + + public static void toProto(User obj, CodedOutputStream output, ProtobufEncodingMode encodingMode) throws IOException { ExpandableIntArray cache = new ExpandableIntArray(16); - UserProtoConverter.computeSize(obj, cache, 0); - UserProtoConverter.toProto(obj, output, cache, 0); + UserProtoConverter.computeSize(obj, cache, 0, encodingMode); + UserProtoConverter.toProto(obj, output, cache, 0, encodingMode); } - public static int toProto(User obj, CodedOutputStream output, ExpandableIntArray cache, int index) throws IOException { + static int toProto(User obj, CodedOutputStream output, ExpandableIntArray cache, int index, ProtobufEncodingMode encodingMode) throws IOException { + boolean compatibleMode = encodingMode == ProtobufEncodingMode.GOOGLE_COMPATIBLE; index = index + 1; - if (obj.getUserName() != null) { + // userName + if (compatibleMode && obj.getUserName() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getUserName() != null) || (compatibleMode && !obj.getUserName().isEmpty())) { output.writeString(1, obj.getUserName()); } - if (obj.getAge() != null) { + // age + if (compatibleMode && obj.getAge() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getAge() != null) || (compatibleMode && obj.getAge() != 0)) { output.writeInt32(2, obj.getAge()); } + // integerListField if (obj.getIntegerListField() != null) { // list | tag | data size | value[0] | value[1] | value[2] | if (obj.getIntegerListField().size() > 0) { @@ -302,15 +331,17 @@ public static int toProto(User obj, CodedOutputStream output, ExpandableIntArray } } } + // structListField if (obj.getStructListField() != null) { // list[0] | tag | data size | value | // list[1] | tag | data size | value | for (Address element: obj.getStructListField()) { output.writeUInt32NoTag(34); output.writeUInt32NoTag(cache.get(index)); - index = AddressProtoConverter.toProto(element, output, cache, index); + index = AddressProtoConverter.toProto(element, output, cache, index, encodingMode); } } + // zonedDateTimeListField if (obj.getZonedDateTimeListField() != null) { // list[0] | tag | data size | value | // list[1] | tag | data size | value | @@ -320,6 +351,7 @@ public static int toProto(User obj, CodedOutputStream output, ExpandableIntArray ZonedDateTimeProtoConverter.toProto(element, output); } } + // jsonListField if (obj.getJsonListField() != null) { // list[0] | tag | data size | value | // list[1] | tag | data size | value | @@ -329,32 +361,56 @@ public static int toProto(User obj, CodedOutputStream output, ExpandableIntArray VertxStructProtoConverter.toProto(element, output); } } + // address if (obj.getAddress() != null) { output.writeUInt32NoTag(58); output.writeUInt32NoTag(cache.get(index)); - index = AddressProtoConverter.toProto(obj.getAddress(), output, cache, index); + index = AddressProtoConverter.toProto(obj.getAddress(), output, cache, index, encodingMode); } + // byteField if (obj.getByteField() != null) { output.writeInt32(8, obj.getByteField()); } - if (obj.getDoubleField() != null) { + // doubleField + if (compatibleMode && obj.getDoubleField() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getDoubleField() != null) || (compatibleMode && obj.getDoubleField() != 0d)) { output.writeDouble(9, obj.getDoubleField()); } - if (obj.getFloatField() != null) { + // floatField + if (compatibleMode && obj.getFloatField() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getFloatField() != null) || (compatibleMode && obj.getFloatField() != 0f)) { output.writeFloat(10, obj.getFloatField()); } - if (obj.getLongField() != null) { + // longField + if (compatibleMode && obj.getLongField() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getLongField() != null) || (compatibleMode && obj.getLongField() != 0L)) { output.writeInt64(11, obj.getLongField()); } - if (obj.getBoolField() != null) { + // boolField + if (compatibleMode && obj.getBoolField() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getBoolField() != null) || (compatibleMode && !obj.getBoolField())) { output.writeBool(12, obj.getBoolField()); } - if (obj.getShortField() != null) { + // shortField + if (compatibleMode && obj.getShortField() == null) { + throw new IllegalArgumentException("Null values are not allowed for boxed types in compatibility mode"); + } + if ((!compatibleMode && obj.getShortField() != null) || (compatibleMode && obj.getShortField() != (short)0)) { output.writeInt32(13, obj.getShortField()); } + // charField if (obj.getCharField() != null) { output.writeInt32(14, obj.getCharField()); } + // stringValueMap if (obj.getStringValueMap() != null) { // map[0] | tag | data size | key | value | // map[1] | tag | data size | key | value | @@ -371,6 +427,7 @@ public static int toProto(User obj, CodedOutputStream output, ExpandableIntArray output.writeString(2, entry.getValue()); } } + // integerValueMap if (obj.getIntegerValueMap() != null) { // map[0] | tag | data size | key | value | // map[1] | tag | data size | key | value | @@ -387,6 +444,7 @@ public static int toProto(User obj, CodedOutputStream output, ExpandableIntArray output.writeInt32(2, entry.getValue()); } } + // structValueMap if (obj.getStructValueMap() != null) { // map[0] | tag | data size | key | value | // map[1] | tag | data size | key | value | @@ -405,9 +463,10 @@ public static int toProto(User obj, CodedOutputStream output, ExpandableIntArray output.writeString(1, entry.getKey()); output.writeUInt32NoTag(18); output.writeUInt32NoTag(elementSize); - index = AddressProtoConverter.toProto(entry.getValue(), output, cache, index); + index = AddressProtoConverter.toProto(entry.getValue(), output, cache, index, encodingMode); } } + // jsonValueMap if (obj.getJsonValueMap() != null) { // map[0] | tag | data size | key | value | // map[1] | tag | data size | key | value | @@ -429,6 +488,7 @@ public static int toProto(User obj, CodedOutputStream output, ExpandableIntArray VertxStructProtoConverter.toProto(entry.getValue(), output); } } + // zonedDateTimeValueMap if (obj.getZonedDateTimeValueMap() != null) { // map[0] | tag | data size | key | value | // map[1] | tag | data size | key | value | @@ -450,50 +510,63 @@ public static int toProto(User obj, CodedOutputStream output, ExpandableIntArray ZonedDateTimeProtoConverter.toProto(entry.getValue(), output); } } + // zonedDateTimeField if (obj.getZonedDateTimeField() != null) { output.writeUInt32NoTag(162); output.writeUInt32NoTag(ZonedDateTimeProtoConverter.computeSize(obj.getZonedDateTimeField())); ZonedDateTimeProtoConverter.toProto(obj.getZonedDateTimeField(), output); } + // instantField if (obj.getInstantField() != null) { output.writeUInt32NoTag(170); output.writeUInt32NoTag(InstantProtoConverter.computeSize(obj.getInstantField())); InstantProtoConverter.toProto(obj.getInstantField(), output); } + // jsonObjectField if (obj.getJsonObjectField() != null) { output.writeUInt32NoTag(178); output.writeUInt32NoTag(VertxStructProtoConverter.computeSize(obj.getJsonObjectField())); VertxStructProtoConverter.toProto(obj.getJsonObjectField(), output); } + // jsonArrayField if (obj.getJsonArrayField() != null) { output.writeUInt32NoTag(186); output.writeUInt32NoTag(VertxStructListProtoConverter.computeSize(obj.getJsonArrayField())); VertxStructListProtoConverter.toProto(obj.getJsonArrayField(), output); } + // primitiveBoolean if (obj.isPrimitiveBoolean()) { output.writeBool(24, obj.isPrimitiveBoolean()); } + // primitiveByte if (obj.getPrimitiveByte() != 0) { output.writeInt32(25, obj.getPrimitiveByte()); } + // primitiveShort if (obj.getPrimitiveShort() != 0) { output.writeInt32(26, obj.getPrimitiveShort()); } + // primitiveInt if (obj.getPrimitiveInt() != 0) { output.writeInt32(27, obj.getPrimitiveInt()); } + // primitiveLong if (obj.getPrimitiveLong() != 0) { output.writeInt64(28, obj.getPrimitiveLong()); } + // primitiveFloat if (obj.getPrimitiveFloat() != 0) { output.writeFloat(29, obj.getPrimitiveFloat()); } + // primitiveDouble if (obj.getPrimitiveDouble() != 0) { output.writeDouble(30, obj.getPrimitiveDouble()); } + // primitiveChar if (obj.getPrimitiveChar() != 0) { output.writeInt32(31, obj.getPrimitiveChar()); } + // enumType if (obj.getEnumType() != null) { switch (obj.getEnumType()) { case A: @@ -511,12 +584,16 @@ public static int toProto(User obj, CodedOutputStream output, ExpandableIntArray } public static int computeSize(User obj) { + return computeSize(obj, ProtobufEncodingMode.VERTX); + } + + public static int computeSize(User obj, ProtobufEncodingMode encodingMode) { ExpandableIntArray cache = new ExpandableIntArray(16); - UserProtoConverter.computeSize(obj, cache, 0); + UserProtoConverter.computeSize(obj, cache, 0, encodingMode); return cache.get(0); } - public static int computeSize(User obj, ExpandableIntArray cache, final int baseIndex) { + static int computeSize(User obj, ExpandableIntArray cache, final int baseIndex, ProtobufEncodingMode encodingMode) { int size = 0; int index = baseIndex + 1; if (obj.getUserName() != null) { @@ -544,7 +621,7 @@ public static int computeSize(User obj, ExpandableIntArray cache, final int base for (Address element: obj.getStructListField()) { size += CodedOutputStream.computeUInt32SizeNoTag(34); int savedIndex = index; - index = AddressProtoConverter.computeSize(element, cache, index); + index = AddressProtoConverter.computeSize(element, cache, index, encodingMode); int dataSize = cache.get(savedIndex); size += CodedOutputStream.computeUInt32SizeNoTag(dataSize); size += dataSize; @@ -578,7 +655,7 @@ public static int computeSize(User obj, ExpandableIntArray cache, final int base if (obj.getAddress() != null) { size += CodedOutputStream.computeUInt32SizeNoTag(58); int savedIndex = index; - index = AddressProtoConverter.computeSize(obj.getAddress(), cache, index); + index = AddressProtoConverter.computeSize(obj.getAddress(), cache, index, encodingMode); int dataSize = cache.get(savedIndex); size += CodedOutputStream.computeUInt32SizeNoTag(dataSize); size += dataSize; @@ -639,7 +716,7 @@ public static int computeSize(User obj, ExpandableIntArray cache, final int base dataSize += CodedOutputStream.computeStringSize(1, entry.getKey()); // value int savedIndex = index; - index = AddressProtoConverter.computeSize(entry.getValue(), cache, index); + index = AddressProtoConverter.computeSize(entry.getValue(), cache, index, encodingMode); int elementSize = cache.get(savedIndex); dataSize += CodedOutputStream.computeInt32SizeNoTag(18); dataSize += CodedOutputStream.computeInt32SizeNoTag(elementSize); diff --git a/vertx-codegen-protobuf/src/converters/java/io/vertx/test/codegen/converter/SimplePojo.java b/vertx-codegen-protobuf/src/converters/java/io/vertx/test/codegen/converter/SimplePojo.java new file mode 100644 index 000000000..7ec210e7d --- /dev/null +++ b/vertx-codegen-protobuf/src/converters/java/io/vertx/test/codegen/converter/SimplePojo.java @@ -0,0 +1,61 @@ +package io.vertx.test.codegen.converter; + +import io.vertx.codegen.annotations.DataObject; +import io.vertx.codegen.protobuf.annotations.FieldNumberStrategy; +import io.vertx.codegen.protobuf.annotations.ProtobufGen; + +import java.util.Objects; + +@DataObject +@ProtobufGen(fieldNumberStrategy = FieldNumberStrategy.COMPACT) +public class SimplePojo { + private Integer integerField; + private Long LongField; + private Boolean booleanField; + private String stringField; + + public Integer getIntegerField() { + return integerField; + } + + public void setIntegerField(Integer integerField) { + this.integerField = integerField; + } + + public Long getLongField() { + return LongField; + } + + public void setLongField(Long longField) { + LongField = longField; + } + + public Boolean getBooleanField() { + return booleanField; + } + + public void setBooleanField(Boolean booleanField) { + this.booleanField = booleanField; + } + + public String getStringField() { + return stringField; + } + + public void setStringField(String stringField) { + this.stringField = stringField; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SimplePojo that = (SimplePojo) o; + return Objects.equals(integerField, that.integerField) && Objects.equals(LongField, that.LongField) && Objects.equals(booleanField, that.booleanField) && Objects.equals(stringField, that.stringField); + } + + @Override + public int hashCode() { + return Objects.hash(integerField, LongField, booleanField, stringField); + } +} diff --git a/vertx-codegen-protobuf/src/main/java/io/vertx/codegen/protobuf/ProtobufEncodingMode.java b/vertx-codegen-protobuf/src/main/java/io/vertx/codegen/protobuf/ProtobufEncodingMode.java new file mode 100644 index 000000000..f8de5156d --- /dev/null +++ b/vertx-codegen-protobuf/src/main/java/io/vertx/codegen/protobuf/ProtobufEncodingMode.java @@ -0,0 +1,19 @@ +package io.vertx.codegen.protobuf; + +/** + * Enumeration representing different encoding modes for Protocol Buffers encoding. + */ +public enum ProtobufEncodingMode { + /** + * In this encoding mode, the converter uses a non-standard protobuf encoding to allow boxed types + * (e.g., Integer, Double) and String to be nullable. This encoding mode is intended for use when + * communicating with another Vert.x converter that supports nullable values. + */ + VERTX, + + /** + * In this encoding mode, the converter uses the standard protobuf encoding, which is compatible with + * Google's protobuf decoder. Null values are not allowed for boxed types and String in this mode. + */ + GOOGLE_COMPATIBLE, +} diff --git a/vertx-codegen-protobuf/src/main/java/io/vertx/codegen/protobuf/generator/DataObjectProtobufGen.java b/vertx-codegen-protobuf/src/main/java/io/vertx/codegen/protobuf/generator/DataObjectProtobufGen.java index 876719f7c..a02b2ef22 100644 --- a/vertx-codegen-protobuf/src/main/java/io/vertx/codegen/protobuf/generator/DataObjectProtobufGen.java +++ b/vertx-codegen-protobuf/src/main/java/io/vertx/codegen/protobuf/generator/DataObjectProtobufGen.java @@ -72,6 +72,7 @@ public String renderProto(DataObjectModel model, int index, int size, Map