package org.ripple.power.blockchain.list;
import static org.ripple.bouncycastle.util.Arrays.concatenate;
import static org.ripple.bouncycastle.util.encoders.Hex.encode;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.ripple.power.utils.ByteUtils;
public class CompactEncoder {
private final static byte TERMINATOR = 16;
private final static Map<Character, Byte> hexMap = new HashMap<Character, Byte>();
static {
hexMap.put('0', (byte) 0x0);
hexMap.put('1', (byte) 0x1);
hexMap.put('2', (byte) 0x2);
hexMap.put('3', (byte) 0x3);
hexMap.put('4', (byte) 0x4);
hexMap.put('5', (byte) 0x5);
hexMap.put('6', (byte) 0x6);
hexMap.put('7', (byte) 0x7);
hexMap.put('8', (byte) 0x8);
hexMap.put('9', (byte) 0x9);
hexMap.put('a', (byte) 0xa);
hexMap.put('b', (byte) 0xb);
hexMap.put('c', (byte) 0xc);
hexMap.put('d', (byte) 0xd);
hexMap.put('e', (byte) 0xe);
hexMap.put('f', (byte) 0xf);
}
public static byte[] packNibbles(byte[] nibbles) {
int terminator = 0;
if (nibbles[nibbles.length - 1] == TERMINATOR) {
terminator = 1;
nibbles = Arrays.copyOf(nibbles, nibbles.length - 1);
}
int oddlen = nibbles.length % 2;
int flag = 2 * terminator + oddlen;
if (oddlen != 0) {
byte[] flags = new byte[] { (byte) flag };
nibbles = concatenate(flags, nibbles);
} else {
byte[] flags = new byte[] { (byte) flag, 0 };
nibbles = concatenate(flags, nibbles);
}
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
for (int i = 0; i < nibbles.length; i += 2) {
buffer.write(16 * nibbles[i] + nibbles[i + 1]);
}
return buffer.toByteArray();
}
public static byte[] unpackToNibbles(byte[] str) {
byte[] base = binToNibbles(str);
base = Arrays.copyOf(base, base.length - 1);
if (base[0] >= 2) {
base = ByteUtils.appendByte(base, TERMINATOR);
}
if (base[0] % 2 == 1) {
base = Arrays.copyOfRange(base, 1, base.length);
} else {
base = Arrays.copyOfRange(base, 2, base.length);
}
return base;
}
public static byte[] binToNibbles(byte[] str) {
byte[] hexEncoded = encode(str);
ByteBuffer slice = ByteBuffer.allocate(hexEncoded.length + 1);
for (byte b : hexEncoded) {
slice.put(hexMap.get((char) b));
}
slice.put(TERMINATOR);
return slice.array();
}
public static byte[] binToNibblesNoTerminator(byte[] str) {
byte[] hexEncoded = encode(str);
ByteBuffer slice = ByteBuffer.allocate(hexEncoded.length);
for (byte b : hexEncoded) {
slice.put(hexMap.get((char) b));
}
return slice.array();
}
}