Validity checks on NamespaceIDs

This commit is contained in:
jglrxavpok 2020-10-18 18:27:57 +02:00
parent 19ab2cbd50
commit 26ce63763a
2 changed files with 87 additions and 2 deletions

View File

@ -1,17 +1,18 @@
package net.minestom.server.utils;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import java.util.regex.Pattern;
/**
* Represents a namespaced ID
* https://minecraft.gamepedia.com/Namespaced_ID
* <p>
* TODO: Implement validity conditions
*/
public class NamespaceID implements CharSequence {
private static final Int2ObjectOpenHashMap<NamespaceID> cache = new Int2ObjectOpenHashMap<>();
private static final String legalLetters = "[0123456789abcdefghijklmnopqrstuvwxyz_-]+";
private final String domain;
private final String path;
@ -28,6 +29,7 @@ public class NamespaceID implements CharSequence {
final int index = namespaceID.indexOf(':');
if (index < 0)
return "minecraft";
assert namespaceID.indexOf(':', index+1) == -1: "Namespace ID can only have at most one colon ':' ("+namespaceID+")";
return namespaceID.substring(0, index);
}
@ -42,6 +44,7 @@ public class NamespaceID implements CharSequence {
final int index = namespaceID.indexOf(':');
if (index < 0)
return namespaceID;
assert namespaceID.indexOf(':', index+1) == -1: "Namespace ID can only have at most one colon ':' ("+namespaceID+")";
return namespaceID.substring(index + 1);
}
@ -68,12 +71,20 @@ public class NamespaceID implements CharSequence {
this.path = path.substring(index + 1);
}
this.full = toString();
validate();
}
private NamespaceID(String domain, String path) {
this.domain = domain;
this.path = path;
this.full = toString();
validate();
}
private void validate() {
assert !domain.contains(".") && !domain.contains("/") : "Domain cannot contain a dot nor a slash character (" + full+ ")";
assert domain.matches(legalLetters) : "Illegal character in domain ("+full+"). Must match "+legalLetters;
assert path.matches(legalLetters) : "Illegal character in path ("+full+"). Must match "+legalLetters;
}
public String getDomain() {
@ -113,6 +124,7 @@ public class NamespaceID implements CharSequence {
return full.subSequence(start, end);
}
@NotNull
@Override
public String toString() {
return domain + ":" + path;

View File

@ -0,0 +1,73 @@
package misc;
import net.minestom.server.utils.NamespaceID;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class TestNamespaceIDValidity {
@Test
public void noErrorWithCorrectFormat() {
NamespaceID.from("minecraft:any");
}
@Test
public void atMostOneColon() {
assertThrows(AssertionError.class, () -> {
NamespaceID.from("minecraft:block:wool");
});
}
@Test
public void noSlashInDomain() {
assertThrows(AssertionError.class, () -> {
NamespaceID.from("minecraft/java_edition:any");
});
}
@Test
public void noDotInDomain() {
assertThrows(AssertionError.class, () -> {
NamespaceID.from("minecraft.java:game");
});
}
@Test
public void noUppercase() {
assertThrows(AssertionError.class, () -> {
NamespaceID.from("Minecraft:any");
});
assertThrows(AssertionError.class, () -> {
NamespaceID.from("minecraft:Any");
});
}
@Test
public void noSpace() {
assertThrows(AssertionError.class, () -> {
NamespaceID.from("minecraft:a n y");
});
}
@Test
public void onlyLatinLowercase() {
assertThrows(AssertionError.class, () -> {
NamespaceID.from("Minecraft:voilà");
});
assertThrows(AssertionError.class, () -> {
NamespaceID.from("minecraft:où_ça");
});
assertThrows(AssertionError.class, () -> {
NamespaceID.from("minecraft:schrödingers_var");
});
}
@Test
public void numbersAllowed() {
NamespaceID.from("0xc1:468786471");
}
}