Skip to content
90 changes: 0 additions & 90 deletions conformance/expected-failures.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,96 +107,6 @@ custom_constraints:
#ERROR: <input>:1:1: expression of type 'int' cannot be range of a comprehension (must be list, map, or dynamic)
# | this.all(e, e == 1)
# | ^
library/is_uri:
- invalid/host/c
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://foo@你好.com"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/host_ipv6/a
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://2001:0db8:85a3:0000:0000:8a2e:0370:7334"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/host_ipv6_zone-id_empty
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[::1%25]"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/host_ipv6_zone-id_unquoted
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[::1%eth0]"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/host_reg-name_pct-encoded_invalid_utf8
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://foo%c3x%96"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/port/a
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://example.com:8a"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/port/b
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://example.com:x"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- invalid/userinfo_reserved_at
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://@@example.com"}
# want: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# got: valid
- valid/host_ipfuture_exhaust
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[vF.-!$&'()*+,;=._~0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
- valid/host_ipfuture_long
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[v1234AF.x]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
- valid/host_ipfuture_short
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[v1.x]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
- valid/host_ipv6_zone-id_pct-encoded_ascii
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[::1%25foo%61%20%23]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
- valid/host_ipv6_zone-id_pct-encoded_utf8
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"https://[::1%25foo%c3%96]"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
- valid/path-empty
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUri]:{val:"foo:"}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri"
# message: ""
library/is_uri_ref:
- valid/empty_string
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUriRef]:{}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri_ref"
# message: ""
- valid/path-empty
# input: [type.googleapis.com/buf.validate.conformance.cases.IsUriRef]:{}
# want: valid
# got: validation error (1 violation)
# 1. constraint_id: "library.is_uri_ref"
# message: ""
standard_constraints/ignore:
- proto/2023/map/ignore_always/invalid/populated
# input: [type.googleapis.com/buf.validate.conformance.cases.EditionsMapIgnoreAlways]:{val:{key:1 value:1}}
Expand Down
Binary file added conformance/src/main/java/build/.DS_Store
Binary file not shown.
96 changes: 45 additions & 51 deletions src/main/java/build/buf/protovalidate/CustomOverload.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
package build.buf.protovalidate;

import com.google.common.primitives.Bytes;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
Expand Down Expand Up @@ -62,19 +60,19 @@ final class CustomOverload {
*/
static Overload[] create() {
return new Overload[] {
format(),
unique(),
startsWith(),
endsWith(),
contains(),
celFormat(),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed all these to stay consistent. I can un-rename them if it's confusing.

celUnique(),
celStartsWith(),
celEndsWith(),
celContains(),
celIsHostname(),
celIsEmail(),
celIsIp(),
celIsIpPrefix(),
celIsUri(),
celIsUriRef(),
isNan(),
isInf(),
celIsNan(),
celIsInf(),
celIsHostAndPort(),
};
}
Expand All @@ -84,7 +82,7 @@ static Overload[] create() {
*
* @return The {@link Overload} instance for the "format" operation.
*/
private static Overload format() {
private static Overload celFormat() {
return Overload.binary(
OVERLOAD_FORMAT,
(lhs, rhs) -> {
Expand All @@ -106,7 +104,7 @@ private static Overload format() {
*
* @return The {@link Overload} instance for the "unique" operation.
*/
private static Overload unique() {
private static Overload celUnique() {
return Overload.unary(
OVERLOAD_UNIQUE,
(val) -> {
Expand All @@ -122,7 +120,7 @@ private static Overload unique() {
*
* @return The {@link Overload} instance for the "startsWith" operation.
*/
private static Overload startsWith() {
private static Overload celStartsWith() {
return Overload.binary(
OVERLOAD_STARTS_WITH,
(lhs, rhs) -> {
Expand Down Expand Up @@ -157,7 +155,7 @@ private static Overload startsWith() {
*
* @return The {@link Overload} instance for the "endsWith" operation.
*/
private static Overload endsWith() {
private static Overload celEndsWith() {
return Overload.binary(
OVERLOAD_ENDS_WITH,
(lhs, rhs) -> {
Expand Down Expand Up @@ -192,7 +190,7 @@ private static Overload endsWith() {
*
* @return The {@link Overload} instance for the "contains" operation.
*/
private static Overload contains() {
private static Overload celContains() {
return Overload.binary(
OVERLOAD_CONTAINS,
(lhs, rhs) -> {
Expand Down Expand Up @@ -262,14 +260,14 @@ private static Overload celIsIp() {
return Err.noSuchOverload(value, OVERLOAD_IS_IP, null);
}
String addr = (String) value.value();
return Types.boolOf(isIP(addr, 0L));
return Types.boolOf(isIp(addr, 0L));
},
(lhs, rhs) -> {
if (lhs.type().typeEnum() != TypeEnum.String || rhs.type().typeEnum() != TypeEnum.Int) {
return Err.noSuchOverload(lhs, OVERLOAD_IS_IP, rhs);
}
String address = (String) lhs.value();
return Types.boolOf(isIP(address, rhs.intValue()));
return Types.boolOf(isIp(address, rhs.intValue()));
},
null);
}
Expand All @@ -289,7 +287,7 @@ private static Overload celIsIpPrefix() {
return Err.noSuchOverload(value, OVERLOAD_IS_IP_PREFIX, null);
}
String prefix = (String) value.value();
return Types.boolOf(isIPPrefix(prefix, 0L, false));
return Types.boolOf(isIpPrefix(prefix, 0L, false));
},
(lhs, rhs) -> {
if (lhs.type().typeEnum() != TypeEnum.String
Expand All @@ -299,9 +297,9 @@ private static Overload celIsIpPrefix() {
}
String prefix = (String) lhs.value();
if (rhs.type().typeEnum() == TypeEnum.Int) {
return Types.boolOf(isIPPrefix(prefix, rhs.intValue(), false));
return Types.boolOf(isIpPrefix(prefix, rhs.intValue(), false));
}
return Types.boolOf(isIPPrefix(prefix, 0L, rhs.booleanValue()));
return Types.boolOf(isIpPrefix(prefix, 0L, rhs.booleanValue()));
},
(values) -> {
if (values.length != 3
Expand All @@ -311,7 +309,7 @@ private static Overload celIsIpPrefix() {
return Err.noSuchOverload(values[0], OVERLOAD_IS_IP_PREFIX, "", values);
}
String prefix = (String) values[0].value();
return Types.boolOf(isIPPrefix(prefix, values[1].intValue(), values[2].booleanValue()));
return Types.boolOf(isIpPrefix(prefix, values[1].intValue(), values[2].booleanValue()));
});
}

Expand All @@ -328,10 +326,7 @@ private static Overload celIsUri() {
return Err.noSuchOverload(value, OVERLOAD_IS_URI, null);
}
String addr = (String) value.value();
if (addr.isEmpty()) {
return BoolT.False;
}
return Types.boolOf(validateURI(addr, true));
return Types.boolOf(isUri(addr));
});
}

Expand All @@ -348,10 +343,7 @@ private static Overload celIsUriRef() {
return Err.noSuchOverload(value, OVERLOAD_IS_URI_REF, null);
}
String addr = (String) value.value();
if (addr.isEmpty()) {
return BoolT.False;
}
return Types.boolOf(validateURI(addr, false));
return Types.boolOf(isUriRef(addr));
});
}

Expand All @@ -360,7 +352,7 @@ private static Overload celIsUriRef() {
*
* @return The {@link Overload} instance for the "isNan" operation.
*/
private static Overload isNan() {
private static Overload celIsNan() {
return Overload.unary(
OVERLOAD_IS_NAN,
value -> {
Expand All @@ -377,7 +369,7 @@ private static Overload isNan() {
*
* @return The {@link Overload} instance for the "isInf" operation.
*/
private static Overload isInf() {
private static Overload celIsInf() {
return Overload.overload(
OVERLOAD_IS_INF,
null,
Expand Down Expand Up @@ -448,21 +440,21 @@ private static boolean isHostAndPort(String str, boolean portRequired) {

int endPlus = end + 1;
if (endPlus == str.length()) { // no port
return !portRequired && isIP(str.substring(1, end), 6);
return !portRequired && isIp(str.substring(1, end), 6);
} else if (endPlus == splitIdx) { // port
return isIP(str.substring(1, end), 6) && isPort(str.substring(splitIdx + 1));
return isIp(str.substring(1, end), 6) && isPort(str.substring(splitIdx + 1));
}
return false; // malformed
}

if (splitIdx < 0) {
return !portRequired && (isHostname(str) || isIP(str, 4));
return !portRequired && (isHostname(str) || isIp(str, 4));
}

String host = str.substring(0, splitIdx);
String port = str.substring(splitIdx + 1);

return ((isHostname(host) || isIP(host, 4)) && isPort(port));
return ((isHostname(host) || isIp(host, 4)) && isPort(port));
}

// Returns true if the string is a valid port for isHostAndPort.
Expand Down Expand Up @@ -606,7 +598,7 @@ private static boolean isHostname(String val) {
* <p>Both formats are well-defined in the internet standard RFC 3986. Zone identifiers for IPv6
* addresses (for example "fe80::a%en1") are supported.
*/
private static boolean isIP(String addr, long ver) {
static boolean isIp(String addr, long ver) {
if (ver == 6L) {
return new Ipv6(addr).address();
} else if (ver == 4L) {
Expand All @@ -618,22 +610,24 @@ private static boolean isIP(String addr, long ver) {
}

/**
* Validates if the input string is a valid URI, which can be a URL or a URN.
* Returns true if the string is a URI, for example "https://example.com/foo/bar?baz=quux#frag".
*
* @param val The input string to validate as a URI.
* @param checkAbsolute Whether to check if this URI is absolute (i.e. has a scheme component)
* @return {@code true} if the input string is a valid URI, {@code false} otherwise.
* <p>URI is defined in the internet standard RFC 3986. Zone Identifiers in IPv6 address literals
* are supported (RFC 6874).
*/
private static boolean validateURI(String val, boolean checkAbsolute) {
try {
URI uri = new URI(val);
if (checkAbsolute) {
return uri.isAbsolute();
}
return true;
} catch (URISyntaxException e) {
return false;
}
private static boolean isUri(String str) {
return new Uri(str).uri();
}

/**
* Returns true if the string is a URI Reference - a URI such as
* "https://example.com/foo/bar?baz=quux#frag", or a Relative Reference such as "./foo/bar?query".
*
* <p>URI, URI Reference, and Relative Reference are defined in the internet standard RFC 3986.
* Zone Identifiers in IPv6 address literals are supported (RFC 6874).
*/
private static boolean isUriRef(String str) {
return new Uri(str).uriReference();
}

/**
Expand All @@ -653,15 +647,15 @@ private static boolean validateURI(String val, boolean checkAbsolute) {
* <p>The same principle applies to IPv4 addresses. "192.168.1.0/24" designates the first 24 bits
* of the 32-bit IPv4 as the network prefix.
*/
private static boolean isIPPrefix(String str, long version, boolean strict) {
private static boolean isIpPrefix(String str, long version, boolean strict) {
if (version == 6L) {
Ipv6 ip = new Ipv6(str);
return ip.addressPrefix() && (!strict || ip.isPrefixOnly());
} else if (version == 4L) {
Ipv4 ip = new Ipv4(str);
return ip.addressPrefix() && (!strict || ip.isPrefixOnly());
} else if (version == 0L) {
return isIPPrefix(str, 6, strict) || isIPPrefix(str, 4, strict);
return isIpPrefix(str, 6, strict) || isIpPrefix(str, 4, strict);
}
return false;
}
Expand Down
Loading
Loading