Skip to content

Commit

Permalink
Add isIpPrefix
Browse files Browse the repository at this point in the history
  • Loading branch information
higebu committed Oct 10, 2023
1 parent df9895c commit 64ed2f1
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 0 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ dependencies {
implementation(enforcedPlatform(libs.cel))
implementation(libs.cel.core)
implementation(libs.guava)
implementation(libs.ipaddress)
implementation(libs.jakarta.mail.api)

testImplementation(libs.assertj)
Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[versions]
assertj = "3.24.2"
cel = "0.3.21"
ipaddress = "5.4.0"
junit = "4.13.2"
# When updating, make sure to update buf.gen.yaml version to match and regenerate code with 'make generate'.
protobuf = "3.24.3"
Expand All @@ -11,6 +12,7 @@ cel = { module = "org.projectnessie.cel:cel-bom", version.ref = "cel" }
cel-core = { module = "org.projectnessie.cel:cel-core" }
errorprone = { module = "com.google.errorprone:error_prone_core", version = "2.22.0" }
guava = { module = "com.google.guava:guava", version = "32.1.2-jre" }
ipaddress = { module = "com.github.seancfoley:ipaddress", version.ref = "ipaddress" }
jakarta-mail-api = { module = "jakarta.mail:jakarta.mail-api", version = "2.1.2" }
junit = { module = "junit:junit", version.ref = "junit" }
maven-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version = "0.25.3" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ static List<Decl> create() {
Decls.newInstanceOverload(
"is_ip_unary", Collections.singletonList(Decls.String), Decls.Bool)));

// Add 'isIpPrefix' function declaration
decls.add(
Decls.newFunction(
"isIpPrefix",
Decls.newInstanceOverload("is_ip_prefix_int_bool", Arrays.asList(Decls.String, Decls.Int, Decls.Bool), Decls.Bool),
Decls.newInstanceOverload("is_ip_prefix_int", Arrays.asList(Decls.String, Decls.Int), Decls.Bool),
Decls.newInstanceOverload("is_ip_prefix_bool", Arrays.asList(Decls.String, Decls.Bool), Decls.Bool),
Decls.newInstanceOverload(
"is_ip_prefix", Collections.singletonList(Decls.String), Decls.Bool)));

// Add 'isUriRef' function declaration
decls.add(
Decls.newFunction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import com.google.common.base.Splitter;
import com.google.common.net.InetAddresses;
import com.google.common.primitives.Bytes;
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressString;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import java.net.Inet4Address;
Expand Down Expand Up @@ -50,6 +52,7 @@ final class CustomOverload {
private static final String OVERLOAD_IS_HOSTNAME = "isHostname";
private static final String OVERLOAD_IS_EMAIL = "isEmail";
private static final String OVERLOAD_IS_IP = "isIp";
private static final String OVERLOAD_IS_IP_PREFIX = "isIpPrefix";
private static final String OVERLOAD_IS_URI = "isUri";
private static final String OVERLOAD_IS_URI_REF = "isUriRef";
private static final String OVERLOAD_IS_NAN = "isNan";
Expand All @@ -70,6 +73,7 @@ static Overload[] create() {
isHostname(),
isEmail(),
isIp(),
isIpPrefix(),
isUri(),
isUriRef(),
isNan(),
Expand Down Expand Up @@ -284,6 +288,53 @@ private static Overload isIp() {
null);
}

/**
* Creates a custom function overload for the "isIpPrefix" operation.
*
* @return The {@link Overload} instance for the "isIpPrefix" operation.
*/
private static Overload isIpPrefix() {
return Overload.overload(
OVERLOAD_IS_IP_PREFIX,
null,
value -> {
if (value.type().typeEnum() != TypeEnum.String && value.type().typeEnum() != TypeEnum.Bool ) {
return Err.noSuchOverload(value, OVERLOAD_IS_IP_PREFIX, null);
}
String prefix = (String) value.value();
if (prefix.isEmpty()) {
return BoolT.False;
}
return Types.boolOf(validateIPPrefix(prefix, 0L, false));
},
(lhs, rhs) -> {
if (lhs.type().typeEnum() != TypeEnum.String || (rhs.type().typeEnum() != TypeEnum.Int && rhs.type().typeEnum() != TypeEnum.Bool)) {
return Err.noSuchOverload(lhs, OVERLOAD_IS_IP_PREFIX, rhs);
}
String prefix = (String) lhs.value();
if (prefix.isEmpty()) {
return BoolT.False;
}
if (rhs.type().typeEnum() == TypeEnum.Int) {
return Types.boolOf(validateIPPrefix(prefix, rhs.intValue(), false));
} else if (rhs.type().typeEnum() == TypeEnum.Bool) {
return Types.boolOf(validateIPPrefix(prefix, 0L, rhs.booleanValue()));
}
return BoolT.False;
},
(values) -> {
if (values[0].type().typeEnum() != TypeEnum.String || values[1].type().typeEnum() != TypeEnum.Int || values[2].type().typeEnum() != TypeEnum.Bool) {
return Err.noSuchOverload(values[0], OVERLOAD_IS_IP_PREFIX, "", new Val[]{values[1], values[2]});
}
String prefix = (String) values[0].value();
if (prefix.isEmpty()) {
return BoolT.False;
}
return Types.boolOf(validateIPPrefix(prefix, values[1].intValue(), values[2].booleanValue()));
}
);
}

/**
* Creates a custom unary function overload for the "isUri" operation.
*
Expand Down Expand Up @@ -494,4 +545,41 @@ private static boolean validateIP(String addr, long ver) {
}
return false;
}

/**
* Validates if the input string is a valid IP prefix.
*
* @param prefix The input string to validate as an IP prefix.
* @param ver The IP version to validate against (0 for any version, 4 for IPv4, 6 for IPv6).
* @param strict If strict is true and host bits are set in the supplied address, then false is returned.
* @return {@code true} if the input string is a valid IP prefix of the specified version, {@code
* false} otherwise.
*/
private static boolean validateIPPrefix(String prefix, long ver, boolean strict) {
IPAddressString str;
IPAddress addr;
try {
str = new IPAddressString(prefix);
addr = str.toAddress();
} catch (Exception e) {
return false;
}
if (!addr.isPrefixed()) {
return false;
}
if (strict) {
IPAddress mask = addr.getNetworkMask().withoutPrefixLength();
if (!addr.mask(mask).equals(str.getHostAddress())) {
return false;
}
}
if (ver == 0L) {
return true;
} else if (ver == 4L) {
return addr.isIPv4();
} else if (ver == 6L) {
return addr.isIPv6();
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,37 @@ public void testUniqueUnsupported() {
}
}

@Test
public void testIsIpPrefix() {
Map<String, Boolean> testCases =
ImmutableMap.<String, Boolean>builder()
.put("'1.2.3.0/24'.isIpPrefix()", true)
.put("'1.2.3.4/24'.isIpPrefix()", true)
.put("'1.2.3.0/24'.isIpPrefix(true)", true)
.put("'1.2.3.4/24'.isIpPrefix(true)", false)
.put("'fd7a:115c:a1e0:ab12:4843:cd96:626b:4000/118'.isIpPrefix()", true)
.put("'fd7a:115c:a1e0:ab12:4843:cd96:626b:430b/118'.isIpPrefix()", true)
.put("'fd7a:115c:a1e0:ab12:4843:cd96:626b:4000/118'.isIpPrefix(true)", true)
.put("'fd7a:115c:a1e0:ab12:4843:cd96:626b:430b/118'.isIpPrefix(true)", false)
.put("'1.2.3.4'.isIpPrefix()", false)
.put("'fd7a:115c:a1e0:ab12:4843:cd96:626b:430b'.isIpPrefix()", false)
.put("'1.2.3.0/24'.isIpPrefix(4)", true)
.put("'1.2.3.4/24'.isIpPrefix(4)", true)
.put("'1.2.3.0/24'.isIpPrefix(4,true)", true)
.put("'1.2.3.4/24'.isIpPrefix(4,true)", false)
.put("'fd7a:115c:a1e0:ab12:4843:cd96:626b:4000/118'.isIpPrefix(4)", false)
.put("'fd7a:115c:a1e0:ab12:4843:cd96:626b:4000/118'.isIpPrefix(6)", true)
.put("'fd7a:115c:a1e0:ab12:4843:cd96:626b:430b/118'.isIpPrefix(6)", true)
.put("'fd7a:115c:a1e0:ab12:4843:cd96:626b:4000/118'.isIpPrefix(6,true)", true)
.put("'fd7a:115c:a1e0:ab12:4843:cd96:626b:430b/118'.isIpPrefix(6,true)", false)
.put("'1.2.3.0/24'.isIpPrefix(6)", false)
.build();
for (Map.Entry<String, Boolean> testCase : testCases.entrySet()) {
Program.EvalResult result = eval(testCase.getKey());
assertThat(result.getVal().booleanValue()).isEqualTo(testCase.getValue());
}
}

private Program.EvalResult eval(String source) {
return eval(source, Activation.emptyActivation());
}
Expand Down

0 comments on commit 64ed2f1

Please sign in to comment.