Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: infinispan/protostream
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 5.0.1.Final
Choose a base ref
...
head repository: infinispan/protostream
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 5.0.2.Final
Choose a head ref
  • 10 commits
  • 30 files changed
  • 4 contributors

Commits on Mar 12, 2024

  1. Next version 5.0.2-SNAPSHOT

    Infinispan committed Mar 12, 2024
    Copy the full SHA
    95a3b65 View commit details

Commits on Apr 5, 2024

  1. Copy the full SHA
    7f21f2a View commit details
  2. Test fixes

    tristantarrant authored and pruivo committed Apr 5, 2024
    Copy the full SHA
    a690bf1 View commit details

Commits on Apr 9, 2024

  1. IPROTO-318 Add support for BitSet.

    Signed-off-by: Pedro Ruivo <pruivo@redhat.com>
    pruivo authored and tristantarrant committed Apr 9, 2024
    Copy the full SHA
    df2d21b View commit details
  2. Use actions/upload-artifact@v3

    * dorny/test-reporter does not support v4 yet.
    
    Fixes the test report GH action.
    
    Signed-off-by: Pedro Ruivo <pruivo@redhat.com>
    pruivo authored and tristantarrant committed Apr 9, 2024
    Copy the full SHA
    bfc0faa View commit details
  3. Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.0 to 3.2.2

    Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.0 to 3.2.2.
    - [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
    - [Commits](apache/maven-gpg-plugin@maven-gpg-plugin-3.2.0...maven-gpg-plugin-3.2.2)
    
    ---
    updated-dependencies:
    - dependency-name: org.apache.maven.plugins:maven-gpg-plugin
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored and tristantarrant committed Apr 9, 2024
    Copy the full SHA
    be32667 View commit details

Commits on Apr 10, 2024

  1. IPROTO-321 Autonumbered fields/enums for schema generation

    * Also add validation before generating the schema
    tristantarrant authored and karesti committed Apr 10, 2024
    Copy the full SHA
    ec836a4 View commit details
  2. Bump org.jboss:jboss-parent from 43 to 44

    Bumps [org.jboss:jboss-parent](https://github.com/jboss/jboss-parent-pom) from 43 to 44.
    - [Release notes](https://github.com/jboss/jboss-parent-pom/releases)
    - [Commits](https://github.com/jboss/jboss-parent-pom/commits)
    
    ---
    updated-dependencies:
    - dependency-name: org.jboss:jboss-parent
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored and tristantarrant committed Apr 10, 2024
    Copy the full SHA
    967055a View commit details
  3. Bump actions/upload-artifact from 3 to 4

    Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
    - [Release notes](https://github.com/actions/upload-artifact/releases)
    - [Commits](actions/upload-artifact@v3...v4)
    
    ---
    updated-dependencies:
    - dependency-name: actions/upload-artifact
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored and tristantarrant committed Apr 10, 2024
    Copy the full SHA
    b883904 View commit details
  4. Releasing 5.0.2.Final

    Infinispan committed Apr 10, 2024
    Copy the full SHA
    879b8a4 View commit details
Showing with 682 additions and 66 deletions.
  1. +1 −1 core/pom.xml
  2. +9 −8 core/src/main/java/org/infinispan/protostream/annotations/impl/AbstractMarshallerCodeGenerator.java
  3. +9 −0 core/src/main/java/org/infinispan/protostream/impl/Log.java
  4. +75 −3 core/src/main/java/org/infinispan/protostream/impl/SparseBitSet.java
  5. +48 −6 core/src/main/java/org/infinispan/protostream/schema/Enum.java
  6. +11 −6 core/src/main/java/org/infinispan/protostream/schema/EnumValue.java
  7. +15 −5 core/src/main/java/org/infinispan/protostream/schema/Field.java
  8. +13 −0 core/src/main/java/org/infinispan/protostream/schema/FieldContainer.java
  9. +6 −4 core/src/main/java/org/infinispan/protostream/schema/Map.java
  10. +49 −6 core/src/main/java/org/infinispan/protostream/schema/Message.java
  11. +22 −8 core/src/main/java/org/infinispan/protostream/schema/OneOf.java
  12. +13 −0 core/src/main/java/org/infinispan/protostream/schema/ReservedNumbers.java
  13. +1 −2 core/src/main/java/org/infinispan/protostream/schema/SchemaWriter.java
  14. +28 −0 core/src/test/java/org/infinispan/protostream/impl/SparseBitSetTest.java
  15. +4 −4 core/src/test/java/org/infinispan/protostream/impl/parser/DescriptorsTest.java
  16. +43 −0 core/src/test/java/org/infinispan/protostream/schema/ProtoBufSchemaTest.java
  17. +1 −1 integrationtests/pom.xml
  18. +2 −2 ...ava/org/infinispan/protostream/integrationtests/processor/AnnotationProcessorCompilationTest.java
  19. +30 −0 ...ava/org/infinispan/protostream/integrationtests/processor/marshaller/GeneratedMarshallerTest.java
  20. +22 −0 ...c/test/java/org/infinispan/protostream/integrationtests/processor/marshaller/model/MapSchema.java
  21. +43 −0 ...est/java/org/infinispan/protostream/integrationtests/processor/marshaller/model/ModelWithMap.java
  22. +10 −0 .../test/java/org/infinispan/protostream/integrationtests/processor/marshaller/model/SimpleEnum.java
  23. +29 −0 ...test/java/org/infinispan/protostream/integrationtests/processor/marshaller/model/UUIDAdapter.java
  24. +3 −3 parent/pom.xml
  25. +2 −2 pom.xml
  26. +1 −1 processor/pom.xml
  27. +32 −1 types/pom.xml
  28. +5 −3 types/src/main/java/org/infinispan/protostream/types/java/CommonTypes.java
  29. +24 −0 types/src/main/java/org/infinispan/protostream/types/java/util/BitSetAdapter.java
  30. +131 −0 types/src/test/java/org/infinispan/protostream/types/java/TypesMarshallingTest.java
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
<parent>
<groupId>org.infinispan.protostream</groupId>
<artifactId>parent</artifactId>
<version>5.0.1.Final</version>
<version>5.0.2.Final</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>

Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@
import org.infinispan.protostream.Message;
import org.infinispan.protostream.SerializationContext;
import org.infinispan.protostream.TagReader;
import org.infinispan.protostream.TagWriter;
import org.infinispan.protostream.WrappedMessage;
import org.infinispan.protostream.annotations.ProtoSchemaBuilderException;
import org.infinispan.protostream.annotations.impl.types.XClass;
@@ -24,6 +23,7 @@
import org.infinispan.protostream.descriptors.JavaType;
import org.infinispan.protostream.descriptors.Type;
import org.infinispan.protostream.descriptors.WireType;
import org.infinispan.protostream.impl.TagWriterImpl;

/**
* @author anistor@readhat.com
@@ -171,7 +171,7 @@ private String makeArrayLocalVar(ProtoFieldMetadata field) {
* Make field name for caching a marshaller delegate for a related message.
*/
protected String makeMarshallerDelegateFieldName(ProtoFieldMetadata field) {
return "__md$" + field.getNumber();
return "__md$" + field.getNumber() + (field.getJavaType().isEnum() ? "e" : "");
}

/**
@@ -599,7 +599,6 @@ private String generateMapFieldReadMethod(ProtoFieldMetadata fieldMetadata, Inde
String mdField = initMarshallerDelegateField(iw, fieldMetadata);
iw.println("int enumVal = $in.readEnum();");
iw.printf("%s = (%s) %s.getMarshaller().decode(enumVal);\n", v, fieldMetadata.getJavaTypeName(), mdField);
iw.println("}");
break;
}
default:
@@ -699,7 +698,7 @@ protected void generateWriteMethodBody(IndentWriter iw, ProtoMessageTypeMetadata
getUnknownFieldSetFieldStatement = "o.getUnknownFieldSet()";
}
if (!messageTypeMetadata.getFields().isEmpty() || getUnknownFieldSetFieldStatement != null) {
iw.printf("final %s $out = $1.getWriter();\n", TagWriter.class.getName());
iw.printf("%s $out = (%s) $1.getWriter();\n", TagWriterImpl.class.getName(), TagWriterImpl.class.getName());
iw.printf("final %s o = (%s) $2;\n", messageTypeMetadata.getJavaClassName(), messageTypeMetadata.getJavaClassName());
for (ProtoFieldMetadata fieldMetadata : messageTypeMetadata.getFields().values()) {
iw.println("{");
@@ -763,10 +762,12 @@ protected void generateWriteMethodBody(IndentWriter iw, ProtoMessageTypeMetadata
);
iw.printf("try (NestedWriter $n = new NestedWriter($1, %d)) {\n", fieldMetadata.getNumber());
iw.inc();
writeFieldValue(mapFieldMetadata.getKey(), iw, v + ".getKey()", "$n.getWriter()");
writeFieldValue(mapFieldMetadata.getValue(), iw, v + ".getValue()", "$n.getWriter()");
iw.println("$out = $n.getWriter();");
writeFieldValue(mapFieldMetadata.getKey(), iw, v + ".getKey()", "$out");
writeFieldValue(mapFieldMetadata.getValue(), iw, v + ".getValue()", "$out");
iw.dec();
iw.println("}");
iw.printf("$out = (%s) $1.getWriter();\n", TagWriterImpl.class.getName());
} else {
iw.printf("for (java.util.Iterator<%s> it = %s.iterator(); it.hasNext(); ) {\n", fieldMetadata.getJavaTypeName(), f);
iw.inc();
@@ -822,7 +823,7 @@ private void writeFieldValue(ProtoFieldMetadata fieldMetadata, IndentWriter iw,
iw.inc();
String mdField = initMarshallerDelegateField(iw, fieldMetadata);
iw.printf("%s.writeTag(%d, %s.impl.WireFormat.WIRETYPE_START_GROUP);\n", out, fieldMetadata.getNumber(), PROTOSTREAM_PACKAGE);
iw.printf("writeMessage(%s, $1, %s);\n", mdField, v);
iw.printf("writeMessage(%s, %s, %s);\n", mdField, out, v);
iw.printf("%s.writeTag(%d, %s.impl.WireFormat.WIRETYPE_END_GROUP);\n", out, fieldMetadata.getNumber(), PROTOSTREAM_PACKAGE);
iw.dec();
iw.println("}");
@@ -832,7 +833,7 @@ private void writeFieldValue(ProtoFieldMetadata fieldMetadata, IndentWriter iw,
iw.println("{");
iw.inc();
String mdField = initMarshallerDelegateField(iw, fieldMetadata);
iw.printf("writeNestedMessage(%s, $1, %d, %s);\n", mdField, fieldMetadata.getNumber(), v);
iw.printf("writeNestedMessage(%s, %s, %d, %s);\n", mdField, out, fieldMetadata.getNumber(), v);
iw.dec();
iw.println("}");
break;
9 changes: 9 additions & 0 deletions core/src/main/java/org/infinispan/protostream/impl/Log.java
Original file line number Diff line number Diff line change
@@ -117,6 +117,15 @@ default MalformedProtobufException messageTruncated() {
@Message(value = "Value `%s` on enum `%s` must be annotated with @ProtoEnumValue", id = 29)
ProtoSchemaBuilderException explicitEnumValueAnnotations(String value, String name);

@Message(value = "Number %d used by field '%s' violates the Protocol Buffer specification", id = 30)
IllegalArgumentException invalidFieldNumber(int number, String name);

@Message(value = "Type '%s' may not mix auto-generated field/enum numbers with explicit and/or reserved numbers", id = 31)
IllegalArgumentException cannotMixAutoGeneratedNumbers(String name);

@Message(value = "Enum '%s' must have a default enum value (with number = 0)", id = 32)
IllegalStateException missingDefaultEnumValue(String name);

class LogFactory {
public static Log getLog(Class<?> clazz) {
return Logger.getMessageLogger(Log.class, clazz.getName());
Original file line number Diff line number Diff line change
@@ -22,14 +22,16 @@
import java.util.NoSuchElementException;
import java.util.PrimitiveIterator;

import org.infinispan.protostream.schema.ReservedNumbers;

/**
* A sparse bit set for storing occurrences of bits where a large amount of the stored bits are expected to be zero.
* This implementation uses a simplistic indexing scheme which provides {@code log(n)} performance for accessing
* individual bits. Memory usage is roughly proportional to {@link #bitCount}. The bit set can set any bit between
* {@code 0} and {@link Long#MAX_VALUE}, inclusive. However, the maximum number of sparse 64-bit words in use by the
* set bits in the bit set is limited by the int length limit of arrays.
*/
public class SparseBitSet {
public class SparseBitSet implements ReservedNumbers {
private long[] words;
private long[] indices;
private int size;
@@ -118,8 +120,16 @@ public boolean set(long i, boolean value) {
return value ? set(i) : clear(i);
}

public void set(long from, long to) {
for (long i = from; i < to; i++) {
/**
* Sets the bits from the specified fromIndex (inclusive) to the specified toIndex (exclusive) to true.
* Params:
*
* @param fromIndex – index of the first bit to be set
* @param toIndex – index after the last bit to be set
* @throws IndexOutOfBoundsException – if fromIndex is negative, or toIndex is negative, or fromIndex is larger than toIndex
*/
public void set(long fromIndex, long toIndex) {
for (long i = fromIndex; i < toIndex; i++) {
set(i);
}
}
@@ -129,6 +139,7 @@ public void set(long from, long to) {
*
* @return {@code true} if the bit at index {@code i} is set, false otherwise.
*/
@Override
public boolean get(long i) {
if (i < 0)
throw new IllegalArgumentException("i < 0: " + i);
@@ -151,6 +162,7 @@ public long bitCount() {
* @return the size of this {@code SparseBitSet}, i.e. the number of set bits.
* @see #bitCount()
*/
@Override
public int size() {
long bitCount = bitCount();

@@ -163,10 +175,70 @@ public int size() {
/**
* @return true if this {@code SparseBitSet} contains no set bits, false otherwise.
*/
@Override
public boolean isEmpty() {
return size == 0;
}

@Override
public int nextSetBit(int fromIndex) {
if (fromIndex < 0) {
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
}
int wordIndex = findWord(fromIndex);
if (wordIndex < 0) {
wordIndex = -wordIndex - 1;
fromIndex = adjustBase(fromIndex, wordIndex);
}
while (wordIndex < size) {
if ((words[wordIndex] & (1L << (fromIndex & 63))) != 0) {
return fromIndex;
}
fromIndex++;
if ((fromIndex % 64) == 0) {
wordIndex = findWord(fromIndex);
if (wordIndex < 0) {
wordIndex = -wordIndex - 1;
fromIndex = adjustBase(fromIndex, wordIndex);
}
}
}
return -1;
}

private int adjustBase(int fromIndex, int wordIndex) {
if (wordIndex < size) {
fromIndex = (int) (indices[wordIndex] << 6);
}
return fromIndex;
}

@Override
public int nextClearBit(int fromIndex) {
if (fromIndex < 0) {
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
}
int wordIndex = findWord(fromIndex);
if (wordIndex < 0) {
wordIndex = -wordIndex - 1;
fromIndex = adjustBase(fromIndex, wordIndex);
}
while (wordIndex < size) {
if ((words[wordIndex] & (1L << (fromIndex & 63))) == 0) {
return fromIndex;
}
fromIndex++;
if ((fromIndex % 64) == 0) {
wordIndex = findWord(fromIndex);
if (wordIndex < 0) {
wordIndex = -wordIndex - 1;
fromIndex = adjustBase(fromIndex, wordIndex);
}
}
}
return -1;
}

/**
* Reset this {@code SparseBitSet} to the empty state, i.e. with no bits set.
*/
54 changes: 48 additions & 6 deletions core/src/main/java/org/infinispan/protostream/schema/Enum.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package org.infinispan.protostream.schema;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import org.infinispan.protostream.impl.Log;
import org.infinispan.protostream.impl.SparseBitSet;

/**
* @since 5.0
*/
@@ -19,13 +23,14 @@ public class Enum {
private final Map<String, Object> options;
private final List<String> comments;
private final Map<String, EnumValue> values;
private final BitSet reservedNumbers;
private final ReservedNumbers reservedNumbers;
private final Set<String> reservedNames;

private Enum(Builder builder) {
this.name = builder.name;
this.fullName = builder.getFullName();
this.values = builder.values.entrySet().stream().collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, e -> e.getValue().create()));
AtomicInteger autoNumber = new AtomicInteger(0);
this.values = builder.values.entrySet().stream().collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, e -> e.getValue().create(autoNumber)));
this.reservedNumbers = builder.reservedNumbers;
this.reservedNames = Set.copyOf(builder.reservedNames);
this.options = Map.copyOf(builder.options);
@@ -52,7 +57,7 @@ public List<String> getComments() {
return comments;
}

public BitSet getReservedNumbers() {
public ReservedNumbers getReservedNumbers() {
return reservedNumbers;
}

@@ -63,8 +68,8 @@ public Set<String> getReservedNames() {
public static class Builder implements CommentContainer<Builder>, ReservedContainer<Builder>, OptionContainer<Builder> {
private final EnumContainer parent;
private final String name;
private final Map<String, EnumValue.Builder> values = new HashMap<>();
private final BitSet reservedNumbers = new BitSet();
private final Map<String, EnumValue.Builder> values = new LinkedHashMap<>();
private final SparseBitSet reservedNumbers = new SparseBitSet();
private final Set<String> reservedNames = new HashSet<>();
private final Map<String, Object> options = new HashMap<>();
private final List<String> comments = new ArrayList<>();
@@ -74,6 +79,10 @@ public static class Builder implements CommentContainer<Builder>, ReservedContai
this.name = name;
}

public EnumValue.Builder addValue(String name) {
return addValue(name, -1);
}

public EnumValue.Builder addValue(String name, int number) {
Objects.requireNonNull(name, "name must not be null");
checkDuplicate(name);
@@ -132,7 +141,40 @@ public Enum.Builder addEnum(String name) {
return parent.addEnum(name);
}

private void validate() {
Boolean autoGenerateNumbers = null;
boolean hasZero = false;
for (EnumValue.Builder v : values.values()) {
if (reservedNames.contains(v.name)) {
throw Log.LOG.reservedName(v.name, name);
}
if (v.number < 0) {
if (Boolean.FALSE.equals(autoGenerateNumbers)) {
throw Log.LOG.cannotMixAutoGeneratedNumbers(name);
} else {
autoGenerateNumbers = Boolean.TRUE;
}
} else {
if (reservedNumbers.get(v.number)) {
throw Log.LOG.reservedNumber(v.number, v.name, name);
}
if (Boolean.TRUE.equals(autoGenerateNumbers)) {
throw Log.LOG.cannotMixAutoGeneratedNumbers(name);
} else {
autoGenerateNumbers = Boolean.FALSE;
}
if (v.number == 0) {
hasZero = true;
}
}
}
if (!hasZero && Boolean.FALSE.equals(autoGenerateNumbers)) {
throw Log.LOG.missingDefaultEnumValue(name);
}
}

Enum create() {
validate();
return new Enum(this);
}

Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
* @since 5.0
@@ -17,10 +18,10 @@ public class EnumValue {
private final Map<String, Object> options;


public EnumValue(Builder builder) {
public EnumValue(Builder builder, AtomicInteger autoNumber) {
this.name = builder.name;
this.fullName = builder.getFullName();
this.number = builder.number;
this.number = builder.number < 0 ? autoNumber.getAndIncrement() : builder.number;
this.comments = List.copyOf(builder.comments);
this.options = Map.copyOf(builder.options);
}
@@ -46,8 +47,8 @@ public Map<String, Object> getOptions() {
}

public static class Builder implements OptionContainer<Builder>, CommentContainer<Builder>, ReservedContainer<Enum.Builder> {
private final String name;
private final int number;
final String name;
final int number;
private final Enum.Builder parent;
private final List<String> comments = new ArrayList<>();
private final Map<String, Object> options = new HashMap<>();
@@ -58,8 +59,8 @@ public static class Builder implements OptionContainer<Builder>, CommentContaine
this.number = number;
}

EnumValue create() {
return new EnumValue(this);
EnumValue create(AtomicInteger autoNumber) {
return new EnumValue(this, autoNumber);
}

public Schema build() {
@@ -77,6 +78,10 @@ public Builder addOption(String name, Object value) {
return this;
}

public EnumValue.Builder addValue(String name) {
return addValue(name, -1);
}

public EnumValue.Builder addValue(String name, int number) {
return parent.addValue(name, number);
}
Loading