package com.bergerkiller.bukkit.common.reflection.classes; import com.bergerkiller.bukkit.common.reflection.ClassTemplate; import com.bergerkiller.bukkit.common.reflection.FieldAccessor; import com.bergerkiller.bukkit.common.reflection.MethodAccessor; import com.bergerkiller.bukkit.common.reflection.NMSClassTemplate; import com.bergerkiller.bukkit.common.reflection.SafeDirectMethod; public class NibbleArrayRef { public static final ClassTemplate<?> TEMPLATE = NMSClassTemplate.create("NibbleArray"); private static final FieldAccessor<byte[]> array = TEMPLATE.getField("a"); public static final FieldAccessor<Integer> bitCount = TEMPLATE.getField("b"); private static final MethodAccessor<Integer> getByteLength; private static final MethodAccessor<Integer> copyToByteArray; private static final MethodAccessor<byte[]> getValueArray; static { // if (Common.IS_SPIGOT_SERVER) { // copyToByteArray = TEMPLATE.getMethod("copyToByteArray", byte[].class, int.class); // getValueArray = TEMPLATE.getMethod("getValueArray"); // getByteLength = TEMPLATE.getMethod("getByteLength"); // } else { copyToByteArray = new SafeDirectMethod<Integer>() { @Override public Integer invoke(Object instance, Object... args) { byte[] data = array.get(instance); byte[] rawBuffer = (byte[]) args[0]; int rawLength = ((Integer) args[1]).intValue(); System.arraycopy(data, 0, rawBuffer, rawLength, data.length); return Integer.valueOf(data.length + rawLength); } }; getValueArray = new SafeDirectMethod<byte[]>() { @Override public byte[] invoke(Object instance, Object... args) { return array.get(instance); } }; getByteLength = new SafeDirectMethod<Integer>() { @Override public Integer invoke(Object instance, Object... args) { return array.get(instance).length; } }; // } } /** * Copies all data contained in the Nibble Array to the byte array specified * * @param nibbleArray to get the data from * @param array to copy to * @param offset in the array to copy at * @return The offset added to the size of the Nibble Array */ public static int copyTo(Object nibbleArray, byte[] array, int offset) { return copyToByteArray.invoke(nibbleArray, array, offset).intValue(); } /** * Obtains a new byte array of the contents of the nibble array * * @param nibbleArray to get te copied array from * @return copied, unreferenced array */ public static byte[] getArrayCopy(Object nibbleArray) { byte[] rval = new byte[getByteLength.invoke(nibbleArray)]; copyTo(nibbleArray, rval, 0); return rval; } /** * Obtains a reference to the byte[] contents of a Nibble Array. * These contents are unsafe for modification, do not change elements of it! * * @param nibbleArray to get the referenced byte array contents of * @return value array */ public static byte[] getValueArray(Object nibbleArray) { return getValueArray.invoke(nibbleArray); } }