Skip to content
Merged
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
2 changes: 2 additions & 0 deletions common/src/main/java/dev/cel/common/values/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,9 @@ java_library(
],
deps = [
":base_proto_cel_value_converter",
":optimized_selectable",
":preadapted_list",
":select_field",
":values",
"//:auto_value",
"//common:options",
Expand Down
76 changes: 60 additions & 16 deletions common/src/main/java/dev/cel/common/values/ProtoMessageValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@

package dev.cel.common.values;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.auto.value.AutoValue;
import com.google.common.base.Preconditions;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
Expand All @@ -28,7 +29,8 @@
/** ProtoMessageValue is a struct value with protobuf support. */
@AutoValue
@Immutable
public abstract class ProtoMessageValue extends StructValue<String, Message> {
public abstract class ProtoMessageValue extends StructValue<String, Message>
implements OptimizedSelectable {

@Override
public abstract Message value();
Expand Down Expand Up @@ -60,28 +62,38 @@ public Optional<Object> find(String field) {
FieldDescriptor fieldDescriptor =
findField(celDescriptorPool(), value().getDescriptorForType(), field);

// Selecting a field on a protobuf message yields a default value even if the field is not
// declared. Therefore, we must exhaustively test whether they are actually declared.
if (fieldDescriptor.isRepeated()) {
if (value().getRepeatedFieldCount(fieldDescriptor) == 0) {
return Optional.empty();
}
} else if (!value().hasField(fieldDescriptor)) {
return Optional.empty();
}
return findFieldValue(fieldDescriptor);
}

return Optional.of(
protoCelValueConverter().fromProtoMessageFieldToCelValue(value(), fieldDescriptor));
@Override
public Object selectByFieldNumber(SelectField field) {
FieldDescriptor fieldDescriptor = findFieldByNumber(value().getDescriptorForType(), field);

return protoCelValueConverter().fromProtoMessageFieldToCelValue(value(), fieldDescriptor);
}

@Override
public boolean hasFieldByNumber(SelectField field) {
FieldDescriptor fieldDescriptor = findFieldByNumber(value().getDescriptorForType(), field);

return isFieldPresent(fieldDescriptor);
}

@Override
public Optional<Object> findByFieldNumber(SelectField field) {
FieldDescriptor fieldDescriptor = findFieldByNumber(value().getDescriptorForType(), field);

return findFieldValue(fieldDescriptor);
}

public static ProtoMessageValue create(
Message value,
CelDescriptorPool celDescriptorPool,
ProtoCelValueConverter protoCelValueConverter,
boolean enableJsonFieldNames) {
Preconditions.checkNotNull(value);
Preconditions.checkNotNull(celDescriptorPool);
Preconditions.checkNotNull(protoCelValueConverter);
checkNotNull(value);
checkNotNull(celDescriptorPool);
checkNotNull(protoCelValueConverter);
return new AutoValue_ProtoMessageValue(
value,
StructTypeReference.create(value.getDescriptorForType().getFullName()),
Expand All @@ -90,6 +102,36 @@ public static ProtoMessageValue create(
enableJsonFieldNames);
}

private Optional<Object> findFieldValue(FieldDescriptor fieldDescriptor) {
if (!isFieldPresent(fieldDescriptor)) {
return Optional.empty();
}

return Optional.of(
protoCelValueConverter().fromProtoMessageFieldToCelValue(value(), fieldDescriptor));
}

private boolean isFieldPresent(FieldDescriptor fieldDescriptor) {
// Selecting a field on a protobuf message yields a default value even if the field is not
// declared. Therefore, we must exhaustively test whether they are actually declared.
if (fieldDescriptor.isRepeated()) {
return value().getRepeatedFieldCount(fieldDescriptor) > 0;
}
return value().hasField(fieldDescriptor);
}

private static FieldDescriptor findFieldByNumber(Descriptor descriptor, SelectField field) {
FieldDescriptor fieldDescriptor = descriptor.findFieldByNumber(field.fieldNumber());
if (fieldDescriptor != null) {
return fieldDescriptor;
}

throw new IllegalArgumentException(
String.format(
"field '%s' (number %d) is not declared in message '%s'",
field.fieldName(), field.fieldNumber(), descriptor.getFullName()));
}

private FieldDescriptor findField(
CelDescriptorPool celDescriptorPool, Descriptor descriptor, String fieldName) {
if (enableJsonFieldNames()) {
Expand All @@ -114,4 +156,6 @@ private FieldDescriptor findField(
"field '%s' is not declared in message '%s'",
fieldName, descriptor.getFullName())));
}

ProtoMessageValue() {}
}
Loading
Loading