package org.ripple.power.blockchain.list;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Queue;
import static org.ripple.bouncycastle.util.Arrays.concatenate;
import static org.ripple.bouncycastle.util.BigIntegers.asUnsignedByteArray;
import org.ripple.power.utils.ByteUtils;
public class RP {
private static double MAX_ITEM_LENGTH = Math.pow(256, 8);
private static int SIZE_THRESHOLD = 56;
private static int OFFSET_SHORT_ITEM = 0x80;
private static int OFFSET_LONG_ITEM = 0xb7;
private static int OFFSET_SHORT_LIST = 0xc0;
private static int OFFSET_LONG_LIST = 0xf7;
private static byte decodeOneByteItem(byte[] data, int index) {
if ((data[index] & 0xFF) == OFFSET_SHORT_ITEM) {
return (byte) (data[index] - OFFSET_SHORT_ITEM);
}
if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) {
return (byte) (data[index]);
}
if ((data[index] & 0xFF) == OFFSET_SHORT_ITEM + 1) {
return (byte) (data[index + 1]);
}
return 0;
}
public static int decodeInt(byte[] data, int index) {
int value = 0;
if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM
&& (data[index] & 0xFF) < OFFSET_LONG_ITEM) {
byte length = (byte) (data[index] - OFFSET_SHORT_ITEM);
byte pow = (byte) (length - 1);
for (int i = 1; i <= length; ++i) {
value += data[index + i] << (8 * pow);
pow--;
}
} else {
throw new RuntimeException("wrong decode attempt");
}
return value;
}
public static short decodeShort(byte[] data, int index) {
short value = 0;
if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM
&& (data[index] & 0xFF) < OFFSET_LONG_ITEM) {
byte length = (byte) (data[index] - OFFSET_SHORT_ITEM);
value = ByteBuffer.wrap(data, index, length).getShort();
} else {
value = data[index];
}
return value;
}
public static long decodeLong(byte[] data, int index) {
long value = 0;
if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM
&& (data[index] & 0xFF) < OFFSET_LONG_ITEM) {
byte length = (byte) (data[index] - OFFSET_SHORT_ITEM);
byte pow = (byte) (length - 1);
for (int i = 1; i <= length; ++i) {
value += data[index + i] << (8 * pow);
pow--;
}
} else {
throw new RuntimeException("wrong decode attempt");
}
return value;
}
public static String decodeStringItem(byte[] data, int index) {
String value = null;
if ((data[index] & 0xFF) >= OFFSET_LONG_ITEM
&& (data[index] & 0xFF) < OFFSET_SHORT_LIST) {
byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_ITEM);
int length = calcLengthRaw(lengthOfLength, data, index);
value = new String(data, index + lengthOfLength + 1, length);
} else if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM
&& (data[index] & 0xFF) < OFFSET_LONG_ITEM) {
byte length = (byte) ((data[index] & 0xFF) - OFFSET_SHORT_ITEM);
value = new String(data, index + 1, length);
} else {
throw new RuntimeException("wrong decode attempt");
}
return value;
}
public static byte[] decodeItemBytes(byte[] data, int index) {
byte[] value = null;
int length = 0;
if ((data[index] & 0xFF) >= OFFSET_LONG_ITEM
&& (data[index] & 0xFF) < OFFSET_SHORT_LIST) {
byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_ITEM);
length = calcLengthRaw(lengthOfLength, data, index);
} else if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM
&& (data[index] & 0xFF) < OFFSET_LONG_ITEM) {
length = (byte) (data[index] - OFFSET_SHORT_ITEM);
} else {
throw new RuntimeException("wrong decode attempt");
}
byte[] valueBytes = new byte[length];
System.arraycopy(data, index, valueBytes, 0, length);
value = valueBytes;
return value;
}
public static BigInteger decodeBigInteger(byte[] data, int index) {
BigInteger value = null;
int length = 0;
if ((data[index] & 0xFF) >= OFFSET_LONG_ITEM
&& (data[index] & 0xFF) < OFFSET_SHORT_LIST) {
byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_ITEM);
length = calcLengthRaw(lengthOfLength, data, index);
} else if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM
&& (data[index] & 0xFF) < OFFSET_LONG_ITEM) {
length = (byte) (data[index] - OFFSET_SHORT_ITEM);
} else {
throw new RuntimeException("wrong decode attempt");
}
byte[] valueBytes = new byte[length];
System.arraycopy(data, index, valueBytes, 0, length);
value = new BigInteger(1, valueBytes);
return value;
}
public static byte[] decodeByteArray(byte[] data, int index) {
byte[] value = null;
int length = 0;
if ((data[index] & 0xFF) >= OFFSET_LONG_ITEM
&& (data[index] & 0xFF) < OFFSET_SHORT_LIST) {
byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_ITEM);
length = calcLengthRaw(lengthOfLength, data, index);
} else if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM
&& (data[index] & 0xFF) < OFFSET_LONG_ITEM) {
length = (byte) (data[index] - OFFSET_SHORT_ITEM);
} else {
throw new RuntimeException("wrong decode attempt");
}
byte[] valueBytes = new byte[length];
System.arraycopy(data, index, valueBytes, 0, length);
value = valueBytes;
return value;
}
public static int nextItemLength(byte[] data, int index) {
if (index >= data.length)
return -1;
if ((data[index] & 0xFF) >= OFFSET_LONG_LIST) {
byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_LIST);
int length = calcLength(lengthOfLength, data, index);
return length;
}
if ((data[index] & 0xFF) >= OFFSET_SHORT_LIST
&& (data[index] & 0xFF) < OFFSET_LONG_LIST) {
byte length = (byte) ((data[index] & 0xFF) - OFFSET_SHORT_LIST);
return length;
}
if ((data[index] & 0xFF) > OFFSET_LONG_ITEM
&& (data[index] & 0xFF) < OFFSET_SHORT_LIST) {
byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_ITEM);
int length = calcLength(lengthOfLength, data, index);
return length;
}
if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM
&& (data[index] & 0xFF) <= OFFSET_LONG_ITEM) {
byte length = (byte) ((data[index] & 0xFF) - OFFSET_SHORT_ITEM);
return length;
}
if ((data[index] & 0xFF) == OFFSET_SHORT_ITEM) {
return 1;
}
if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) {
return 1;
}
return -1;
}
public static byte[] decodeIP4Bytes(byte[] data, int index) {
int offset = 1;
byte aByte = decodeOneByteItem(data, index + offset);
if ((data[index + offset] & 0xFF) > OFFSET_SHORT_ITEM) {
offset = offset + 2;
} else {
offset = offset + 1;
}
byte bByte = decodeOneByteItem(data, index + offset);
if ((data[index + offset] & 0xFF) > OFFSET_SHORT_ITEM) {
offset = offset + 2;
} else {
offset = offset + 1;
}
byte cByte = decodeOneByteItem(data, index + offset);
if ((data[index + offset] & 0xFF) > OFFSET_SHORT_ITEM) {
offset = offset + 2;
} else {
offset = offset + 1;
}
byte dByte = decodeOneByteItem(data, index + offset);
return new byte[] { aByte, bByte, cByte, dByte };
}
public static int getFirstListElement(byte[] payload, int pos) {
if (pos >= payload.length)
return -1;
if ((payload[pos] & 0xFF) >= OFFSET_LONG_LIST) {
byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_LIST);
return pos + lengthOfLength + 1;
}
if ((payload[pos] & 0xFF) >= OFFSET_SHORT_LIST
&& (payload[pos] & 0xFF) < OFFSET_LONG_LIST) {
return pos + 1;
}
if ((payload[pos] & 0xFF) >= OFFSET_LONG_ITEM
&& (payload[pos] & 0xFF) < OFFSET_SHORT_LIST) {
byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_ITEM);
return pos + lengthOfLength + 1;
}
return -1;
}
public static int getNextElementIndex(byte[] payload, int pos) {
if (pos >= payload.length)
return -1;
if ((payload[pos] & 0xFF) >= OFFSET_LONG_LIST) {
byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_LIST);
int length = calcLength(lengthOfLength, payload, pos);
return pos + lengthOfLength + length + 1;
}
if ((payload[pos] & 0xFF) >= OFFSET_SHORT_LIST
&& (payload[pos] & 0xFF) < OFFSET_LONG_LIST) {
byte length = (byte) ((payload[pos] & 0xFF) - OFFSET_SHORT_LIST);
return pos + 1 + length;
}
if ((payload[pos] & 0xFF) >= OFFSET_LONG_ITEM
&& (payload[pos] & 0xFF) < OFFSET_SHORT_LIST) {
byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_ITEM);
int length = calcLength(lengthOfLength, payload, pos);
return pos + lengthOfLength + length + 1;
}
if ((payload[pos] & 0xFF) > OFFSET_SHORT_ITEM
&& (payload[pos] & 0xFF) < OFFSET_LONG_ITEM) {
byte length = (byte) ((payload[pos] & 0xFF) - OFFSET_SHORT_ITEM);
return pos + 1 + length;
}
if ((payload[pos] & 0xFF) == OFFSET_SHORT_ITEM) {
return pos + 1;
}
if ((payload[pos] & 0xFF) < OFFSET_SHORT_ITEM) {
return pos + 1;
}
return -1;
}
public static void fullTraverse(byte[] msgData, int level, int startPos,
int endPos, int levelToIndex, Queue<Integer> index) {
try {
if (msgData == null || msgData.length == 0) {
return;
}
int pos = startPos;
while (pos < endPos) {
if (level == levelToIndex) {
index.add(new Integer(pos));
}
if ((msgData[pos] & 0xFF) >= OFFSET_LONG_LIST) {
byte lengthOfLength = (byte) (msgData[pos] - OFFSET_LONG_LIST);
int length = calcLength(lengthOfLength, msgData, pos);
fullTraverse(msgData, level + 1, pos + lengthOfLength + 1,
pos + lengthOfLength + length, levelToIndex, index);
pos += lengthOfLength + length + 1;
continue;
}
if ((msgData[pos] & 0xFF) >= OFFSET_SHORT_LIST
&& (msgData[pos] & 0xFF) < OFFSET_LONG_LIST) {
byte length = (byte) ((msgData[pos] & 0xFF) - OFFSET_SHORT_LIST);
System.out.println("-- level: [" + level
+ "] Found small list length: " + length);
fullTraverse(msgData, level + 1, pos + 1, pos + length + 1,
levelToIndex, index);
pos += 1 + length;
continue;
}
if ((msgData[pos] & 0xFF) >= OFFSET_LONG_ITEM
&& (msgData[pos] & 0xFF) < OFFSET_SHORT_LIST) {
byte lengthOfLength = (byte) (msgData[pos] - OFFSET_LONG_ITEM);
int length = calcLength(lengthOfLength, msgData, pos);
pos += lengthOfLength + length + 1;
continue;
}
if ((msgData[pos] & 0xFF) > OFFSET_SHORT_ITEM
&& (msgData[pos] & 0xFF) < OFFSET_LONG_ITEM) {
byte length = (byte) ((msgData[pos] & 0xFF) - OFFSET_SHORT_ITEM);
pos += 1 + length;
continue;
}
if ((msgData[pos] & 0xFF) == OFFSET_SHORT_ITEM) {
pos += 1;
continue;
}
if ((msgData[pos] & 0xFF) < OFFSET_SHORT_ITEM) {
pos += 1;
continue;
}
}
} catch (Throwable th) {
throw new RuntimeException("RLP wrong encoding",
th.fillInStackTrace());
}
}
private static int calcLength(int lengthOfLength, byte[] msgData, int pos) {
byte pow = (byte) (lengthOfLength - 1);
int length = 0;
for (int i = 1; i <= lengthOfLength; ++i) {
length += (msgData[pos + i] & 0xFF) << (8 * pow);
pow--;
}
return length;
}
private static int calcLengthRaw(int lengthOfLength, byte[] msgData,
int index) {
byte pow = (byte) (lengthOfLength - 1);
int length = 0;
for (int i = 1; i <= lengthOfLength; ++i) {
length += msgData[index + i] << (8 * pow);
pow--;
}
return length;
}
public static byte getCommandCode(byte[] data) {
byte command = 0;
int index = getFirstListElement(data, 0);
command = data[index];
command = ((int) (command & 0xFF) == OFFSET_SHORT_ITEM) ? 0 : command;
return command;
}
public static RPList decode2(byte[] msgData) {
RPList rlpList = new RPList();
fullTraverse(msgData, 0, 0, msgData.length, 1, rlpList);
return rlpList;
}
private static void fullTraverse(byte[] msgData, int level, int startPos,
int endPos, int levelToIndex, RPList rlpList) {
try {
if (msgData == null || msgData.length == 0) {
return;
}
int pos = startPos;
while (pos < endPos) {
if ((msgData[pos] & 0xFF) > OFFSET_LONG_LIST) {
byte lengthOfLength = (byte) (msgData[pos] - OFFSET_LONG_LIST);
int length = calcLength(lengthOfLength, msgData, pos);
byte[] rlpData = new byte[lengthOfLength + length + 1];
System.arraycopy(msgData, pos, rlpData, 0, lengthOfLength
+ length + 1);
RPList newLevelList = new RPList();
newLevelList.setRLPData(rlpData);
fullTraverse(msgData, level + 1, pos + lengthOfLength + 1,
pos + lengthOfLength + length + 1, levelToIndex,
newLevelList);
rlpList.add(newLevelList);
pos += lengthOfLength + length + 1;
continue;
}
if ((msgData[pos] & 0xFF) >= OFFSET_SHORT_LIST
&& (msgData[pos] & 0xFF) <= OFFSET_LONG_LIST) {
byte length = (byte) ((msgData[pos] & 0xFF) - OFFSET_SHORT_LIST);
byte[] rlpData = new byte[length + 1];
System.arraycopy(msgData, pos, rlpData, 0, length + 1);
RPList newLevelList = new RPList();
newLevelList.setRLPData(rlpData);
if (length > 0)
fullTraverse(msgData, level + 1, pos + 1, pos + length
+ 1, levelToIndex, newLevelList);
rlpList.add(newLevelList);
pos += 1 + length;
continue;
}
if ((msgData[pos] & 0xFF) > OFFSET_LONG_ITEM
&& (msgData[pos] & 0xFF) < OFFSET_SHORT_LIST) {
byte lengthOfLength = (byte) (msgData[pos] - OFFSET_LONG_ITEM);
int length = calcLength(lengthOfLength, msgData, pos);
byte[] item = new byte[length];
System.arraycopy(msgData, pos + lengthOfLength + 1, item,
0, length);
byte[] rlpPrefix = new byte[lengthOfLength + 1];
System.arraycopy(msgData, pos, rlpPrefix, 0,
lengthOfLength + 1);
RPItem rlpItem = new RPItem(item);
rlpList.add(rlpItem);
pos += lengthOfLength + length + 1;
continue;
}
if ((msgData[pos] & 0xFF) > OFFSET_SHORT_ITEM
&& (msgData[pos] & 0xFF) <= OFFSET_LONG_ITEM) {
byte length = (byte) ((msgData[pos] & 0xFF) - OFFSET_SHORT_ITEM);
byte[] item = new byte[length];
System.arraycopy(msgData, pos + 1, item, 0, length);
byte[] rlpPrefix = new byte[2];
System.arraycopy(msgData, pos, rlpPrefix, 0, 2);
RPItem rlpItem = new RPItem(item);
rlpList.add(rlpItem);
pos += 1 + length;
continue;
}
if ((msgData[pos] & 0xFF) == OFFSET_SHORT_ITEM) {
byte[] item = ByteUtils.EMPTY_BYTE_ARRAY;
RPItem rlpItem = new RPItem(item);
rlpList.add(rlpItem);
pos += 1;
continue;
}
if ((msgData[pos] & 0xFF) < OFFSET_SHORT_ITEM) {
byte[] item = { (byte) (msgData[pos] & 0xFF) };
RPItem rlpItem = new RPItem(item);
rlpList.add(rlpItem);
pos += 1;
continue;
}
}
} catch (Exception e) {
throw new RuntimeException("RLP wrong encoding", e);
}
}
public static DecodeResult decode(byte[] data, int pos) {
if (data == null || data.length < 1) {
return null;
}
int prefix = data[pos] & 0xFF;
if (prefix == OFFSET_SHORT_ITEM) {
return new DecodeResult(pos + 1, "");
} else if (prefix < OFFSET_SHORT_ITEM) {
return new DecodeResult(pos + 1, new byte[] { data[pos] });
} else if (prefix < OFFSET_LONG_ITEM) {
int len = prefix - OFFSET_SHORT_ITEM;
return new DecodeResult(pos + 1 + len, Arrays.copyOfRange(data,
pos + 1, pos + 1 + len));
} else if (prefix < OFFSET_SHORT_LIST) {
int lenlen = prefix - OFFSET_LONG_ITEM;
int lenbytes = ByteUtils.byteArrayToInt(Arrays.copyOfRange(data,
pos + 1, pos + 1 + lenlen));
return new DecodeResult(pos + 1 + lenlen + lenbytes,
Arrays.copyOfRange(data, pos + 1 + lenlen, pos + 1 + lenlen
+ lenbytes));
} else if (prefix <= OFFSET_LONG_LIST) {
int len = prefix - OFFSET_SHORT_LIST;
int prevPos = pos;
pos++;
return decodeList(data, pos, prevPos, len);
} else if (prefix < 0xFF) {
int lenlen = prefix - OFFSET_LONG_LIST;
int lenlist = ByteUtils.byteArrayToInt(Arrays.copyOfRange(data,
pos + 1, pos + 1 + lenlen));
pos = pos + lenlen + 1;
int prevPos = lenlist;
return decodeList(data, pos, prevPos, lenlist);
} else {
throw new RuntimeException(
"Only byte values between 0x00 and 0xFF are supported, but got: "
+ prefix);
}
}
private static DecodeResult decodeList(byte[] data, int pos, int prevPos,
int len) {
List<Object> slice = new ArrayList<Object>();
for (int i = 0; i < len;) {
DecodeResult result = decode(data, pos);
slice.add(result.getDecoded());
prevPos = result.getPos();
i += (prevPos - pos);
pos = prevPos;
}
return new DecodeResult(pos, slice.toArray());
}
public static byte[] encode(Object input) {
Value val = new Value(input);
if (val.isList()) {
List<Object> inputArray = val.asList();
if (inputArray.size() == 0) {
return encodeLength(inputArray.size(), OFFSET_SHORT_LIST);
}
byte[] output = ByteUtils.EMPTY_BYTE_ARRAY;
for (Object object : inputArray) {
output = concatenate(output, encode(object));
}
byte[] prefix = encodeLength(output.length, OFFSET_SHORT_LIST);
return concatenate(prefix, output);
} else {
byte[] inputAsBytes = toBytes(input);
if (inputAsBytes.length == 1) {
return inputAsBytes;
} else {
byte[] firstByte = encodeLength(inputAsBytes.length,
OFFSET_SHORT_ITEM);
return concatenate(firstByte, inputAsBytes);
}
}
}
public static byte[] encodeLength(int length, int offset) {
if (length < SIZE_THRESHOLD) {
byte firstByte = (byte) (length + offset);
return new byte[] { firstByte };
} else if (length < MAX_ITEM_LENGTH) {
byte[] binaryLength;
if (length > 0xFF)
binaryLength = BigInteger.valueOf(length).toByteArray();
else
binaryLength = new byte[] { (byte) length };
byte firstByte = (byte) (binaryLength.length + offset
+ SIZE_THRESHOLD - 1);
return concatenate(new byte[] { firstByte }, binaryLength);
} else {
throw new RuntimeException("Input too long");
}
}
public static byte[] encodeByte(byte singleByte) {
if ((singleByte & 0xFF) == 0) {
return new byte[] { (byte) OFFSET_SHORT_ITEM };
} else if ((singleByte & 0xFF) < 0x7F) {
return new byte[] { singleByte };
} else {
return new byte[] { (byte) (OFFSET_SHORT_ITEM + 1), singleByte };
}
}
public static byte[] encodeShort(short singleShort) {
if (singleShort <= 0xFF)
return encodeByte((byte) singleShort);
else {
return new byte[] { (byte) (OFFSET_SHORT_ITEM + 2),
(byte) (singleShort >> 8 & 0xFF),
(byte) (singleShort >> 0 & 0xFF) };
}
}
public static byte[] encodeInt(int singleInt) {
if (singleInt <= 0xFF) {
return encodeByte((byte) singleInt);
} else if (singleInt <= 0xFFFF) {
return encodeShort((short) singleInt);
} else if (singleInt <= 0xFFFFFF) {
return new byte[] { (byte) (OFFSET_SHORT_ITEM + 3),
(byte) (singleInt >>> 16), (byte) (singleInt >>> 8),
(byte) singleInt };
} else {
return new byte[] { (byte) (OFFSET_SHORT_ITEM + 4),
(byte) (singleInt >>> 24), (byte) (singleInt >>> 16),
(byte) (singleInt >>> 8), (byte) singleInt };
}
}
public static byte[] encodeString(String srcString) {
return encodeElement(srcString.getBytes());
}
public static byte[] encodeBigInteger(BigInteger srcBigInteger) {
if (srcBigInteger == BigInteger.ZERO)
return encodeByte((byte) 0);
else
return encodeElement(asUnsignedByteArray(srcBigInteger));
}
public static byte[] encodeElement(byte[] srcData) {
if (srcData == null) {
return new byte[] { (byte) OFFSET_SHORT_ITEM };
} else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) {
return srcData;
} else if (srcData.length < SIZE_THRESHOLD) {
byte length = (byte) (OFFSET_SHORT_ITEM + srcData.length);
byte[] data = Arrays.copyOf(srcData, srcData.length + 1);
System.arraycopy(data, 0, data, 1, srcData.length);
data[0] = length;
return data;
} else {
int tmpLength = srcData.length;
byte byteNum = 0;
while (tmpLength != 0) {
++byteNum;
tmpLength = tmpLength >> 8;
}
byte[] lenBytes = new byte[byteNum];
for (int i = 0; i < byteNum; ++i) {
lenBytes[byteNum - 1 - i] = (byte) ((srcData.length >> (8 * i)) & 0xFF);
}
byte[] data = Arrays.copyOf(srcData, srcData.length + 1 + byteNum);
System.arraycopy(data, 0, data, 1 + byteNum, srcData.length);
data[0] = (byte) (OFFSET_LONG_ITEM + byteNum);
System.arraycopy(lenBytes, 0, data, 1, lenBytes.length);
return data;
}
}
public static byte[] encodeList(byte[]... elements) {
if (elements == null) {
return new byte[] { (byte) OFFSET_SHORT_LIST };
}
int totalLength = 0;
for (int i = 0; elements != null && i < elements.length; ++i) {
totalLength += elements[i].length;
}
byte[] data;
int copyPos = 0;
if (totalLength < SIZE_THRESHOLD) {
data = new byte[1 + totalLength];
data[0] = (byte) (OFFSET_SHORT_LIST + totalLength);
copyPos = 1;
} else {
int tmpLength = totalLength;
byte byteNum = 0;
while (tmpLength != 0) {
++byteNum;
tmpLength = tmpLength >> 8;
}
tmpLength = totalLength;
byte[] lenBytes = new byte[byteNum];
for (int i = 0; i < byteNum; ++i) {
lenBytes[byteNum - 1 - i] = (byte) ((tmpLength >> (8 * i)) & 0xFF);
}
data = new byte[1 + lenBytes.length + totalLength];
data[0] = (byte) (OFFSET_LONG_LIST + byteNum);
System.arraycopy(lenBytes, 0, data, 1, lenBytes.length);
copyPos = lenBytes.length + 1;
}
for (int i = 0; i < elements.length; ++i) {
System.arraycopy(elements[i], 0, data, copyPos, elements[i].length);
copyPos += elements[i].length;
}
return data;
}
private static byte[] toBytes(Object input) {
if (input instanceof byte[]) {
return (byte[]) input;
} else if (input instanceof String) {
String inputString = (String) input;
return inputString.getBytes();
} else if (input instanceof Long) {
Long inputLong = (Long) input;
return (inputLong == 0) ? ByteUtils.EMPTY_BYTE_ARRAY
: asUnsignedByteArray(BigInteger.valueOf(inputLong));
} else if (input instanceof Integer) {
Integer inputInt = (Integer) input;
return (inputInt == 0) ? ByteUtils.EMPTY_BYTE_ARRAY
: asUnsignedByteArray(BigInteger.valueOf(inputInt
.intValue()));
} else if (input instanceof BigInteger) {
BigInteger inputBigInt = (BigInteger) input;
return (inputBigInt == BigInteger.ZERO) ? ByteUtils.EMPTY_BYTE_ARRAY
: asUnsignedByteArray(inputBigInt);
} else if (input instanceof Value) {
Value val = (Value) input;
return toBytes(val.asObj());
}
throw new RuntimeException(
"Unsupported type: Only accepting String, Integer and BigInteger for now");
}
}