#3841, #3842: Speed up TagUtil#fromJson()

Reduce complexity and recursive calls
This commit is contained in:
Outfluencer 2025-06-04 06:50:02 +10:00 committed by md_5
parent 1f159f8eaa
commit 93508d5083
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11
2 changed files with 102 additions and 5 deletions

View File

@ -32,6 +32,87 @@ import net.md_5.bungee.nbt.type.StringTag;
public final class TagUtil public final class TagUtil
{ {
private static byte nbtTypeOfJson(JsonElement json)
{
if ( json instanceof JsonPrimitive )
{
JsonPrimitive jsonPrimitive = (JsonPrimitive) json;
if ( jsonPrimitive.isNumber() )
{
Number number = json.getAsNumber();
if ( number instanceof Byte )
{
return Tag.BYTE;
} else if ( number instanceof Short )
{
return Tag.SHORT;
} else if ( number instanceof Integer )
{
return Tag.INT;
} else if ( number instanceof Long )
{
return Tag.LONG;
} else if ( number instanceof Float )
{
return Tag.FLOAT;
} else if ( number instanceof Double )
{
return Tag.DOUBLE;
}
} else if ( jsonPrimitive.isString() )
{
return Tag.STRING;
} else if ( jsonPrimitive.isBoolean() )
{
return Tag.BYTE;
}
throw new IllegalArgumentException( "Unknown JSON primitive: " + jsonPrimitive );
} else if ( json instanceof JsonObject )
{
return Tag.COMPOUND;
} else if ( json instanceof JsonArray )
{
JsonArray array = json.getAsJsonArray();
Byte listType = null;
for ( JsonElement jsonEl : array )
{
byte type = nbtTypeOfJson( jsonEl );
if ( listType == null )
{
listType = type;
} else if ( listType != type )
{
listType = Tag.COMPOUND;
break;
}
}
if ( listType == null )
{
return Tag.LIST;
}
switch ( listType )
{
case Tag.BYTE:
return Tag.BYTE_ARRAY;
case Tag.INT:
return Tag.INT_ARRAY;
case Tag.LONG:
return Tag.LONG_ARRAY;
default:
return Tag.LIST;
}
} else if ( json instanceof JsonNull )
{
return Tag.END;
}
throw new IllegalArgumentException( "Unknown JSON element: " + json );
}
public static TypedTag fromJson(JsonElement json) public static TypedTag fromJson(JsonElement json)
{ {
if ( json instanceof JsonPrimitive ) if ( json instanceof JsonPrimitive )
@ -66,10 +147,8 @@ public final class TagUtil
} else if ( jsonPrimitive.isBoolean() ) } else if ( jsonPrimitive.isBoolean() )
{ {
return new ByteTag( (byte) ( jsonPrimitive.getAsBoolean() ? 1 : 0 ) ); return new ByteTag( (byte) ( jsonPrimitive.getAsBoolean() ? 1 : 0 ) );
} else
{
throw new IllegalArgumentException( "Unknown JSON primitive: " + jsonPrimitive );
} }
throw new IllegalArgumentException( "Unknown JSON primitive: " + jsonPrimitive );
} else if ( json instanceof JsonObject ) } else if ( json instanceof JsonObject )
{ {
CompoundTag compoundTag = new CompoundTag( new LinkedHashMap<>() ); CompoundTag compoundTag = new CompoundTag( new LinkedHashMap<>() );
@ -87,7 +166,7 @@ public final class TagUtil
for ( JsonElement jsonEl : jsonArray ) for ( JsonElement jsonEl : jsonArray )
{ {
byte type = fromJson( jsonEl ).getId(); byte type = nbtTypeOfJson( jsonEl );
if ( listType == null ) if ( listType == null )
{ {
listType = type; listType = type;
@ -98,8 +177,13 @@ public final class TagUtil
} }
} }
if ( listType == null ) if ( listType == null || listType == Tag.END )
{ {
if ( !jsonArray.isEmpty() )
{
throw new IllegalArgumentException( "Invalid end tag in json array: " + json );
}
return new ListTag( Collections.emptyList(), Tag.END ); return new ListTag( Collections.emptyList(), Tag.END );
} }

View File

@ -5,6 +5,7 @@ import com.google.gson.Gson;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive; import com.google.gson.JsonPrimitive;
import net.md_5.bungee.nbt.Tag; import net.md_5.bungee.nbt.Tag;
import net.md_5.bungee.nbt.TypedTag; import net.md_5.bungee.nbt.TypedTag;
@ -224,4 +225,16 @@ public class TagUtilTest
assertEquals( array.get( i ).getAsString(), string.getValue() ); assertEquals( array.get( i ).getAsString(), string.getValue() );
} }
} }
@Test
public void testRecursive()
{
JsonElement jsonElement = JsonParser.parseString( "{\"extra\":[{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"}],\"text\":\"\"},{\"extra\":[{\"extra\":[{\"color\":\"#FF0000\",\"text\":\"f\"},{\"color\":\"#00FFFF\",\"text\":\"<\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}],\"text\":\"\"}\n" );
long start = System.currentTimeMillis();
TagUtil.fromJson( jsonElement );
long end = System.currentTimeMillis();
System.out.println( "Time passed: " + ( end - start ) + "ms" );
}
} }