package de.geolykt.starplane.remapping; import java.util.Locale; import org.jetbrains.annotations.NotNull; import org.objectweb.asm.Opcodes; final class AccessUtil { private static final String[] ACCESS_STRING_CACHE_128 = new String[] { null, "ACC_TRANSIENT", "ACC_VARARGS", null }; private static final String[] ACCESS_STRING_CACHE_32 = new String[] { "ACC_SUPER", "ACC_TRANSITIVE", // Somehow I want to debate that. But where would "open" go then? "ACC_SYNCHRONIZED", "ACC_OPEN" }; private static final String[] ACCESS_STRING_CACHE_32768 = new String[] { "ACC_MODULE", null, null, "ACC_MANDATED" }; private static final String[] ACCESS_STRING_CACHE_64 = new String[] { "ACC_BRIDGE", "ACC_VOLATILE", null, null }; public static final int ANY_VISIBILITY_MODIFIER = Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED; @NotNull private static final String @NotNull[] ERROR_CODES = new @NotNull String[] { "No further information", "Access flag already exists", "Access flag does not yet exist", "Internal transformation failure: Transform is not valid.", "Another visibility-controlling access flag already exists." }; static final long ERROR_FLAG_EXISTS = 1L << 32; static final long ERROR_FLAG_NOT_EXISTS = ERROR_FLAG_EXISTS + 1; static final long ERROR_TRANSFORM_VALIDITY_ERROR = ERROR_FLAG_NOT_EXISTS + 1; static final long ERROR_VISBILITY_CONFLICT = ERROR_TRANSFORM_VALIDITY_ERROR + 1; static final long INT_LSB = 0xFFFFFFFFL; public static final int TARGET_ANY = -1; public static final int TARGET_CLASS = 0; public static final int TARGET_FIELD = 1; public static final int TARGET_METHOD = 2; public static final int TARGET_MODULE = 3; public static int andAccessTypes(int leftAccessType, int rightAccessType) { if (leftAccessType == TARGET_ANY) { return rightAccessType; } else if (rightAccessType == TARGET_ANY) { return leftAccessType; } else if (leftAccessType == rightAccessType) { return leftAccessType; } else { throw new IllegalArgumentException("Access categories cannot be combined with AND: " + leftAccessType + ", " + rightAccessType); } } public static final int getAccessCategory(String string) { switch (string.toUpperCase(Locale.ROOT)) { case "0": return TARGET_ANY; case "ACC_ABSTRACT": case "ABSTRACT": return TARGET_ANY; case "ACC_ANNOTATION": case "ANNOTATION": return TARGET_CLASS; case "ACC_DEPRECATED": case "DEPRECATED": return TARGET_ANY; case "ACC_ENUM": case "ENUM": return TARGET_ANY; // Note: this is also applied to enum-generated fields or something like that. So TARGET_ANY is used. case "ACC_FINAL": case "FINAL": return TARGET_ANY; case "ACC_INTERFACE": case "INTERFACE": return TARGET_CLASS; case "ACC_NATIVE": case "NATIVE": return TARGET_METHOD; case "ACC_PRIVATE": case "PRIVATE": return TARGET_ANY; case "ACC_PROTECTED": case "PROTECTED": return TARGET_ANY; case "ACC_PUBLIC": case "PUBLIC": return TARGET_ANY; case "ACC_RECORD": case "RECORD": return TARGET_CLASS; case "ACC_STATIC": case "STATIC": return TARGET_ANY; case "ACC_STRICT": case "STRICTFP": return TARGET_METHOD; case "ACC_SYNTHETIC": case "SYNTHETIC": return TARGET_ANY; case "ACC_SUPER": case "SUPER": return TARGET_CLASS; case "ACC_SYNCHRONIZED": case "SYNCHRONIZED": return TARGET_METHOD; case "ACC_TRANSITIVE": case "TRANSITIVE": return TARGET_FIELD; case "ACC_OPEN": case "OPEN": return TARGET_MODULE; case "ACC_BRIDGE": case "BRIDGE": return TARGET_METHOD; case "ACC_VOLATILE": case "VOLATILE": return TARGET_FIELD; case "ACC_VARARGS": case "VARARGS": return TARGET_METHOD; case "ACC_TRANSIENT": case "TRANSIENT": return TARGET_MODULE; case "ACC_MODULE": case "MODULE": return TARGET_CLASS; case "ACC_MANDATED": case "MANDATED": return TARGET_MODULE; default: throw new IllegalArgumentException(string); } } @NotNull static final String getErrorCode(long result) { return ERROR_CODES[(int) (result >> 32)]; } public static final int parseAccess(String string) { switch (string.toUpperCase(Locale.ROOT)) { case "0": return 0; case "ACC_ABSTRACT": case "ABSTRACT": return Opcodes.ACC_ABSTRACT; case "ACC_ANNOTATION": case "ANNOTATION": return Opcodes.ACC_ANNOTATION; case "ACC_DEPRECATED": case "DEPRECATED": return Opcodes.ACC_DEPRECATED; case "ACC_ENUM": case "ENUM": return Opcodes.ACC_ENUM; case "ACC_FINAL": case "FINAL": return Opcodes.ACC_FINAL; case "ACC_INTERFACE": case "INTERFACE": return Opcodes.ACC_INTERFACE; case "ACC_NATIVE": case "NATIVE": return Opcodes.ACC_NATIVE; case "ACC_PRIVATE": case "PRIVATE": return Opcodes.ACC_PRIVATE; case "ACC_PROTECTED": case "PROTECTED": return Opcodes.ACC_PROTECTED; case "ACC_PUBLIC": case "PUBLIC": return Opcodes.ACC_PUBLIC; case "ACC_RECORD": case "RECORD": return Opcodes.ACC_RECORD; case "ACC_STATIC": case "STATIC": return Opcodes.ACC_STATIC; case "ACC_STRICT": case "STRICTFP": return Opcodes.ACC_STRICT; case "ACC_SYNTHETIC": case "SYNTHETIC": return Opcodes.ACC_SYNTHETIC; case "ACC_SUPER": case "SUPER": return Opcodes.ACC_SUPER; case "ACC_SYNCHRONIZED": case "SYNCHRONIZED": return Opcodes.ACC_SYNCHRONIZED; case "ACC_TRANSITIVE": case "TRANSITIVE": return Opcodes.ACC_TRANSITIVE; case "ACC_OPEN": case "OPEN": return Opcodes.ACC_OPEN; case "ACC_BRIDGE": case "BRIDGE": return Opcodes.ACC_BRIDGE; case "ACC_VOLATILE": case "VOLATILE": return Opcodes.ACC_VOLATILE; case "ACC_VARARGS": case "VARARGS": return Opcodes.ACC_VARARGS; case "ACC_TRANSIENT": case "TRANSIENT": return Opcodes.ACC_TRANSIENT; case "ACC_MODULE": case "MODULE": return Opcodes.ACC_MODULE; case "ACC_MANDATED": case "MANDATED": return Opcodes.ACC_MANDATED; default: throw new IllegalArgumentException(string); } } public static final String stringifyAccess(int access, int type) { switch (access) { case 0: return "0"; case 32: return ACCESS_STRING_CACHE_32[type]; case 64: return ACCESS_STRING_CACHE_64[type]; case 128: return ACCESS_STRING_CACHE_128[type]; case 32768: return ACCESS_STRING_CACHE_32768[type]; case Opcodes.ACC_ABSTRACT: return "ACC_ABSTRACT"; case Opcodes.ACC_ANNOTATION: return "ACC_ANNOTATION"; case Opcodes.ACC_DEPRECATED: return "ACC_DEPRECATED"; case Opcodes.ACC_ENUM: return "ACC_ENUM"; case Opcodes.ACC_FINAL: return "ACC_FINAL"; case Opcodes.ACC_INTERFACE: return "ACC_INTERFACE"; case Opcodes.ACC_NATIVE: return "ACC_NATIVE"; case Opcodes.ACC_PRIVATE: return "ACC_PRIVATE"; case Opcodes.ACC_PROTECTED: return "ACC_PROTECTED"; case Opcodes.ACC_PUBLIC: return "ACC_PUBLIC"; case Opcodes.ACC_RECORD: return "ACC_RECORD"; case Opcodes.ACC_STATIC: return "ACC_STATIC"; case Opcodes.ACC_STRICT: return "ACC_STRICT"; case Opcodes.ACC_SYNTHETIC: return "ACC_SYNTHETIC"; default: return "???"; } } }