Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -667,8 +667,23 @@ public static String getFieldsCompareToStatements(final List<Field> fields, Stri
}
"""
.replace("$fieldName", f.nameCamelFirstLower());
} else if (f.type() == Field.FieldType.STRING
|| f.type() == Field.FieldType.BYTES
} else if (f.type() == Field.FieldType.STRING) {
generatedCodeSoFar += """
if ($fieldName == null && thatObj.$fieldName != null) {
return -1;
}
if ($fieldName != null && thatObj.$fieldName == null) {
return 1;
}
if ($fieldName != null) {
result = Arrays.compare($fieldName, thatObj.$fieldName);
}
if (result != 0) {
return result;
}
"""
.replace("$fieldName", f.nameCamelFirstLower());
} else if (f.type() == Field.FieldType.BYTES
|| f.type() == Field.FieldType.ENUM) {
generatedCodeSoFar += generateCompareToForObject(f);
} else if (f.type() == Field.FieldType.MESSAGE || f.type() == Field.FieldType.ONE_OF) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static com.hedera.pbj.compiler.impl.Common.snakeToCamel;

import com.hedera.pbj.compiler.impl.grammar.Protobuf3Parser;
import com.hedera.pbj.compiler.impl.grammar.Protobuf3Parser.MessageDefContext;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.function.Consumer;

Expand All @@ -17,6 +18,9 @@
@SuppressWarnings("unused")
public interface Field {

/** Annotation to add to fields that can't be set to null */
String NON_NULL_ANNOTATION = "@NonNull";

/** The default maximum size of a repeated or length-encoded field (Bytes, String, Message, etc.).
* The size should not be increased beyond the current limit because of the safety concerns.
*/
Expand Down Expand Up @@ -91,6 +95,17 @@ default String nameCamelFirstLower() {
*/
String javaFieldType();

/**
* Get the Java storage field type for this field, this allows for fields to be stored in a different format than
* they are presented to the user, for example String fields are stored as byte array. Normally this is the same as
* {@link #javaFieldType()} except for a few special cases.
*
* @return this fields type in Java format
*/
default String javaFieldStorageType() {
return javaFieldType();
}

/**
* Get the Java field type for this field.
* Unlike {@link #javaFieldType()}, this method returns the base type for repeated and oneOf fields.
Expand All @@ -106,6 +121,83 @@ default String nameCamelFirstLower() {
*/
String methodNameType();

/**
* Check if the storage type is different from the exposed type, this is true for String fields which are stored
* as byte arrays.
*
* @return true if storage type is different from exposed type, otherwise false
*/
default boolean hasDifferentStorageType() {
return !javaFieldStorageType().equals(javaFieldType());
}

/**
* Get the code for setting storage field, by default a no-op. This can be used for fields like String where we
* want different internal storage types.
*
* @param inputVarName the name of the variable being passed in to the setter
* @param msgDef the message definition
* @param lookupHelper the lookup helper
* @return code for setting storage field
*/
default String storageFieldSetter(final String inputVarName, final MessageDefContext msgDef,
final ContextualLookupHelper lookupHelper) {
if (canBeNull()) {
return inputVarName + " != null ? " + inputVarName + " : " + defaultValue(msgDef, lookupHelper);
} else {
return inputVarName;
}
}

/**
* Get the code for getting storage field, by default a no-op. This can be used for fields like String where we
* want different internal storage types.
*
* @param fieldName the name of the field being accessed
* @return code for getting storage field
*/
default String storageFieldGetter(String fieldName) {
return fieldName;
}

/**
* Determine if this field can be null or not. Repeated fields cannot be null, they are empty lists when not set.
* Message and Enum fields can be null, all other field types cannot be null.
*
* @return true if this field can be null, otherwise false
*/
default boolean canBeNull() {
if (repeated()) return false;
return switch (type()) {
case MESSAGE, ENUM -> true;
default -> false;
};
}

/**
* Get a set of annotations for this field.
*
* @return an empty string, or a string with Java annotations ending with a space
*/
default String annotations() {
return canBeNull() ? "" : NON_NULL_ANNOTATION + " ";
}

/**
* Gets the default value for this field
*
* @param msgDef the message definition
* @param lookupHelper the lookup helper
* @return the generated code
*/
default String defaultValue(final MessageDefContext msgDef, final ContextualLookupHelper lookupHelper) {
if (type() == Field.FieldType.ONE_OF) {
return lookupHelper.getFullyQualifiedMessageClassname(FileType.CODEC, msgDef) + "." + javaDefault();
} else {
return javaDefault();
}
}

/**
* Add all the needed imports for this field to the supplied set.
*
Expand Down Expand Up @@ -276,7 +368,7 @@ enum FieldType {
/** Protobuf sfixed64(signed fixed encoding long) field type */
SFIXED64("long", "Long", "0", TYPE_FIXED64),
/** Protobuf string field type */
STRING("String", "String", "\"\"", TYPE_LENGTH_DELIMITED),
STRING("String", "String", "PbjConstants.EMPTY_BYTES", TYPE_LENGTH_DELIMITED),
/** Protobuf bool(boolean) field type */
BOOL("boolean", "Boolean", "false", TYPE_VARINT),
/** Protobuf bytes field type */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ public MapField(Protobuf3Parser.MapFieldContext mapContext, final ContextualLook
"An internal, private map entry key for %s"
.formatted(mapContext.mapName().getText()),
false,
null),
null,
true),
new SingleField(
false,
FieldType.of(mapContext.type_(), lookupHelper),
Expand All @@ -73,7 +74,8 @@ public MapField(Protobuf3Parser.MapFieldContext mapContext, final ContextualLook
"An internal, private map entry value for %s"
.formatted(mapContext.mapName().getText()),
false,
null),
null,
true),
false, // maps cannot be repeated
Integer.parseInt(mapContext.fieldNumber().getText()),
mapContext.mapName().getText(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static com.hedera.pbj.compiler.impl.Common.DEFAULT_INDENT;

import com.hedera.pbj.compiler.impl.grammar.Protobuf3Parser;
import com.hedera.pbj.compiler.impl.grammar.Protobuf3Parser.MessageDefContext;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.function.Consumer;

Expand Down Expand Up @@ -31,7 +32,8 @@ public record SingleField(
String messageTypeTestPackage,
String comment,
boolean deprecated,
OneOfField parent)
OneOfField parent,
boolean isMapField)
implements Field {

/**
Expand All @@ -55,7 +57,7 @@ public SingleField(Protobuf3Parser.FieldContext fieldContext, final ContextualLo
Common.buildCleanFieldJavaDoc(
Integer.parseInt(fieldContext.fieldNumber().getText()), fieldContext.docComment()),
getDeprecatedOption(fieldContext.fieldOptions()),
null);
null, false);
}

/**
Expand Down Expand Up @@ -96,7 +98,8 @@ public SingleField(
Common.buildCleanFieldJavaDoc(
Integer.parseInt(fieldContext.fieldNumber().getText()), fieldContext.docComment()),
getDeprecatedOption(fieldContext.fieldOptions()),
parent);
parent,
false);
}

/**
Expand Down Expand Up @@ -124,19 +127,46 @@ public String protobufFieldType() {
return type == SingleField.FieldType.MESSAGE ? messageType : type.javaType;
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
@Override
public String javaFieldType() {
return javaFieldType(true);
}

/** {@inheritDoc} */
@Override
public String javaFieldTypeBase() {
return javaFieldType(false);
}

/** {@inheritDoc} */
@Override
public String javaFieldStorageType() {
if (type == FieldType.STRING) {
return repeated ? "List<byte[]>" : "byte[]";
}
return javaFieldType();
}

/** {@inheritDoc} */
@Override
public String storageFieldSetter(final String inputVarName, final MessageDefContext msgDef,
final ContextualLookupHelper lookupHelper) {
if (type == FieldType.STRING && parent == null && !isMapField) {
return "toUtf8Bytes("+inputVarName+")";
} else if (canBeNull()) {
return inputVarName + " != null ? " + inputVarName + " : " + defaultValue(msgDef, lookupHelper);
} else {
return inputVarName;
}
}

/** {@inheritDoc} */
@Override
public String storageFieldGetter(String fieldName) {
return type == FieldType.STRING ? "toUtf8String("+fieldName+")" : fieldName;
}

@NonNull
private String javaFieldType(boolean considerRepeated) {
String fieldType =
Expand Down
Loading
Loading