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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
setup_only: true
token: ${{ secrets.BUF_TOKEN }}
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
uses: gradle/actions/wrapper-validation@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
- name: Lint
run: make lint
- name: Generate
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/conformance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ jobs:
setup_only: true
token: ${{ secrets.BUF_TOKEN }}
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
uses: gradle/actions/wrapper-validation@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
- name: Test conformance
run: make conformance
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
setup_only: true
token: ${{ secrets.BUF_TOKEN }}
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
uses: gradle/actions/wrapper-validation@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
- name: Configure GPG signing & publish
env:
GPG_KEY: ${{ secrets.GPG_KEY }}
Expand Down
8 changes: 4 additions & 4 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[versions]
assertj = "3.27.7"
buf = "1.70.0"
cel = "0.13.0"
error-prone = "2.49.0"
cel = "0.13.1"
error-prone = "2.50.0"
junit = "5.14.4"
maven-publish = "0.36.0"
protobuf = "4.35.0"
protobuf = "4.35.1"
re2j = "1.8"

[libraries]
Expand All @@ -14,7 +14,7 @@ buf = { module = "build.buf:buf", version.ref = "buf" }
cel = { module = "dev.cel:cel", version.ref = "cel" }
errorprone-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "error-prone" }
errorprone-core = { module = "com.google.errorprone:error_prone_core", version.ref = "error-prone" }
grpc-protobuf = { module = "io.grpc:grpc-protobuf", version = "1.81.0" }
grpc-protobuf = { module = "io.grpc:grpc-protobuf", version = "1.82.0" }
jspecify = { module ="org.jspecify:jspecify", version = "1.0.0" }
junit-bom = { module = "org.junit:junit-bom", version.ref = "junit" }
maven-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "maven-publish" }
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/build/buf/protovalidate/AnyEvaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import build.buf.validate.FieldPath;
import build.buf.validate.FieldRules;
import com.google.protobuf.Descriptors;
import com.google.protobuf.Message;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
Expand Down Expand Up @@ -78,12 +77,12 @@ final class AnyEvaluator implements Evaluator {
@Override
public List<RuleViolation.Builder> evaluate(Value val, boolean failFast)
throws ExecutionException {
Message anyValue = val.messageValue();
ValidateMessage anyValue = val.messageValue();
if (anyValue == null) {
return RuleViolation.NO_VIOLATIONS;
}
List<RuleViolation.Builder> violationList = new ArrayList<>();
String typeURL = (String) anyValue.getField(typeURLDescriptor);
String typeURL = anyValue.getField(typeURLDescriptor).jvmValue(String.class);
if (!in.isEmpty() && !in.contains(typeURL)) {
RuleViolation.Builder violation =
RuleViolation.newBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ public List<RuleViolation.Builder> evaluate(Value val, boolean failFast)
RuleBase.add(
violations,
NativeViolations.newViolation(
IN_SITE, null, "must be in list " + formatList(inVals), val, bytesVal));
IN_SITE, null, "must be in list " + formatList(inVals), val, inVals));
if (failFast) return base.done(violations);
}

Expand All @@ -437,7 +437,7 @@ public List<RuleViolation.Builder> evaluate(Value val, boolean failFast)
null,
"must not be in list " + formatList(notInVals),
val,
bytesVal));
notInVals));
if (failFast) return base.done(violations);
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/build/buf/protovalidate/CelPrograms.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public boolean tautology() {
@Override
public List<RuleViolation.Builder> evaluate(Value val, boolean failFast)
throws ExecutionException {
CelVariableResolver bindings = Variable.newThisVariable(val.value(Object.class));
CelVariableResolver bindings = Variable.newThisVariable(val.celValue());
List<RuleViolation.Builder> violations = new ArrayList<>();
for (CompiledProgram program : programs) {
RuleViolation.Builder violation = program.eval(val, bindings);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/build/buf/protovalidate/EnumEvaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public boolean tautology() {
@Override
public List<RuleViolation.Builder> evaluate(Value val, boolean failFast)
throws ExecutionException {
Object enumValue = val.value(Object.class);
Long enumValue = val.jvmValue(Long.class);
if (enumValue == null) {
return RuleViolation.NO_VIOLATIONS;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/build/buf/protovalidate/EnumRulesEvaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public List<RuleViolation.Builder> evaluate(Value val, boolean failFast) {
if (!inVals.isEmpty() && !inVals.contains(actual)) {
RuleViolation.Builder b =
NativeViolations.newViolation(
IN_SITE, null, "must be in list " + RuleBase.formatList(inVals), val, actual);
IN_SITE, null, "must be in list " + RuleBase.formatList(inVals), val, inVals);
violations = RuleBase.add(violations, b);
if (failFast) {
return base.done(violations);
Expand All @@ -136,7 +136,7 @@ public List<RuleViolation.Builder> evaluate(Value val, boolean failFast) {
null,
"must not be in list " + RuleBase.formatList(notInVals),
val,
actual);
notInVals);
violations = RuleBase.add(violations, b);
if (failFast) {
return base.done(violations);
Expand Down
15 changes: 8 additions & 7 deletions src/main/java/build/buf/protovalidate/FieldEvaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import build.buf.validate.FieldRules;
import build.buf.validate.Ignore;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Message;
import java.util.Collections;
import java.util.List;

Expand Down Expand Up @@ -95,7 +94,7 @@ public List<RuleViolation.Builder> evaluate(Value val, boolean failFast)
if (this.shouldIgnoreAlways()) {
return RuleViolation.NO_VIOLATIONS;
}
Message message = val.messageValue();
ValidateMessage message = val.messageValue();
if (message == null) {
return RuleViolation.NO_VIOLATIONS;
}
Expand All @@ -113,17 +112,19 @@ public List<RuleViolation.Builder> evaluate(Value val, boolean failFast)
if (this.shouldIgnoreEmpty() && !hasField) {
return RuleViolation.NO_VIOLATIONS;
}
return valueEvaluator.evaluate(
new ObjectValue(descriptor, message.getField(descriptor)), failFast);
return valueEvaluator.evaluate(message.getField(descriptor), failFast);
}

/**
* Returns whether the given field is set on the message. Handles repeated and map fields, which
* are not supported by {@link Message#hasField}.
* require inspecting the list/map contents rather than a presence bit.
*/
static boolean isFieldSet(Message message, FieldDescriptor field) {
static boolean isFieldSet(ValidateMessage message, FieldDescriptor field) {
if (field.isRepeated()) {
return message.getRepeatedFieldCount(field) != 0;
if (field.isMapField()) {
return !message.getField(field).mapValue().isEmpty();
}
return !message.getField(field).repeatedValue().isEmpty();
}
return message.hasField(field);
}
Expand Down
11 changes: 8 additions & 3 deletions src/main/java/build/buf/protovalidate/ListElementValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,20 @@ final class ListElementValue implements Value {
}

@Override
public @Nullable Message messageValue() {
public @Nullable ValidateMessage messageValue() {
if (fieldDescriptor.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
return (Message) value;
return new ProtobufValidateMessage((Message) value);
}
return null;
}

@Override
public <T> T value(Class<T> clazz) {
public Object celValue() {
return ProtoAdapter.scalarToCel(fieldDescriptor.getType(), value);
}

@Override
public <T> T jvmValue(Class<T> clazz) {
Descriptors.FieldDescriptor.Type type = fieldDescriptor.getType();
if (type == Descriptors.FieldDescriptor.Type.MESSAGE) {
return clazz.cast(value);
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/build/buf/protovalidate/MapEvaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,19 @@ private List<RuleViolation.Builder> evalPairs(Value key, Value value, boolean fa
case TYPE_SINT64:
case TYPE_SFIXED32:
case TYPE_SFIXED64:
fieldPathElementBuilder.setIntKey(key.value(Number.class).longValue());
fieldPathElementBuilder.setIntKey(key.jvmValue(Number.class).longValue());
break;
case TYPE_UINT32:
case TYPE_UINT64:
case TYPE_FIXED32:
case TYPE_FIXED64:
fieldPathElementBuilder.setUintKey(key.value(Number.class).longValue());
fieldPathElementBuilder.setUintKey(key.jvmValue(Number.class).longValue());
break;
case TYPE_BOOL:
fieldPathElementBuilder.setBoolKey(key.value(Boolean.class));
fieldPathElementBuilder.setBoolKey(key.jvmValue(Boolean.class));
break;
case TYPE_STRING:
fieldPathElementBuilder.setStringKey(key.value(String.class));
fieldPathElementBuilder.setStringKey(key.jvmValue(String.class));
break;
default:
throw new ExecutionException("Unexpected map key type");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import build.buf.protovalidate.exceptions.ExecutionException;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Message;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -45,7 +44,7 @@ public boolean tautology() {
@Override
public List<RuleViolation.Builder> evaluate(Value val, boolean failFast)
throws ExecutionException {
Message msg = val.messageValue();
ValidateMessage msg = val.messageValue();
if (msg == null) {
return RuleViolation.NO_VIOLATIONS;
}
Expand Down
20 changes: 13 additions & 7 deletions src/main/java/build/buf/protovalidate/MessageValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,15 @@
/** The {@link Value} type that contains a {@link com.google.protobuf.Message}. */
final class MessageValue implements Value {

/** Object type since the object type is inferred from the field descriptor. */
private final Object value;
private final ProtobufValidateMessage value;

/**
* Constructs a {@link MessageValue} with the provided message value.
*
* @param value The message value.
*/
MessageValue(Message value) {
this.value = value;
this.value = new ProtobufValidateMessage(value);
}

@Override
Expand All @@ -42,13 +41,20 @@ final class MessageValue implements Value {
}

@Override
public Message messageValue() {
return (Message) value;
public ValidateMessage messageValue() {
return value;
}

@Override
public Object celValue() {
return value.getMessage();
}

@Override
public <T> T value(Class<T> clazz) {
return clazz.cast(value);
public <T> T jvmValue(Class<T> clazz) {
throw new UnsupportedOperationException(
"jvmValue returns a raw scalar for native rule evaluation and is not supported on a message"
+ " value; use messageValue() or celValue() instead");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public List<RuleViolation.Builder> evaluate(Value val, boolean failFast) {
null,
"must be in list " + formatList(inVals),
val,
actual));
inVals));
if (failFast) {
return base.done(violations);
}
Expand All @@ -251,7 +251,7 @@ public List<RuleViolation.Builder> evaluate(Value val, boolean failFast) {
null,
"must not be in list " + formatList(notInVals),
val,
actual));
notInVals));
if (failFast) {
return base.done(violations);
}
Expand All @@ -263,7 +263,7 @@ public List<RuleViolation.Builder> evaluate(Value val, boolean failFast) {
Objects.requireNonNull(
config.descriptors.finiteSite, "finiteSite must be set when finite is true");
violations =
RuleBase.add(violations, NativeViolations.newViolation(site, null, null, val, actual));
RuleBase.add(violations, NativeViolations.newViolation(site, null, null, val, true));
if (failFast) {
return base.done(violations);
}
Expand Down
14 changes: 11 additions & 3 deletions src/main/java/build/buf/protovalidate/ObjectValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,23 @@ public Descriptors.FieldDescriptor fieldDescriptor() {

@Nullable
@Override
public Message messageValue() {
public ValidateMessage messageValue() {
if (fieldDescriptor.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
return (Message) value;
return new ProtobufValidateMessage((Message) value);
}
return null;
}

@Override
public <T> T value(Class<T> clazz) {
public Object celValue() {
return ProtoAdapter.toCel(fieldDescriptor, value);
}

@Override
public <T> T jvmValue(Class<T> clazz) {
if (value instanceof Descriptors.EnumValueDescriptor) {
return clazz.cast((long) ((Descriptors.EnumValueDescriptor) value).getNumber());
}
return clazz.cast(ProtoAdapter.toCel(fieldDescriptor, value));
}

Expand Down
9 changes: 6 additions & 3 deletions src/main/java/build/buf/protovalidate/OneofEvaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import build.buf.protovalidate.exceptions.ExecutionException;
import build.buf.validate.FieldPathElement;
import com.google.protobuf.Descriptors.OneofDescriptor;
import com.google.protobuf.Message;
import java.util.Collections;
import java.util.List;

Expand Down Expand Up @@ -48,8 +47,12 @@ public boolean tautology() {
@Override
public List<RuleViolation.Builder> evaluate(Value val, boolean failFast)
throws ExecutionException {
Message message = val.messageValue();
if (message == null || !required || (message.getOneofFieldDescriptor(descriptor) != null)) {
ValidateMessage message = val.messageValue();
if (message == null) {
return RuleViolation.NO_VIOLATIONS;
}
boolean hasField = descriptor.getFields().stream().anyMatch(message::hasField);
if (!required || hasField) {
return RuleViolation.NO_VIOLATIONS;
}
return Collections.singletonList(
Expand Down
Loading