package com.ripple.core.serialized; import com.ripple.core.fields.Field; import com.ripple.encodings.common.B16; public class BinaryParser { protected final int size; protected byte[] bytes; protected int cursor = 0; public BinaryParser(byte[] bytes) { this.size = bytes.length; this.bytes = bytes; } public BinaryParser(int size) { this.size = size; } public BinaryParser(String hex) { this(B16.decode(hex)); } public void skip(int n) { cursor += n; } public byte readOne() { return bytes[cursor++]; } public byte[] read(int n) { byte[] ret = new byte[n]; System.arraycopy(bytes, cursor, ret, 0, n); cursor += n; // } return ret; } public Field readField() { int fieldCode = readFieldCode(); Field field = Field.fromCode(fieldCode); if (field == null) { throw new IllegalStateException("Couldn't parse field from " + Integer.toHexString(fieldCode)); } return field; } public int readFieldCode() { byte tagByte = readOne(); int typeBits = (tagByte & 0xFF) >>> 4; if (typeBits == 0) typeBits = readOne(); int fieldBits = tagByte & 0x0F; if (fieldBits == 0) fieldBits = readOne(); return (typeBits << 16 | fieldBits); } public boolean end() { return cursor >= size; // greater guard against infinite loops } public int pos() { return cursor; } public int readOneInt() { return readOne() & 0xFF; } public int readVLLength() { int b1 = readOneInt(); int result; if (b1 <= 192) { result = b1; } else if (b1 <= 240) { int b2 = readOneInt(); result = 193 + (b1 - 193) * 256 + b2; } else if (b1 <= 254) { int b2 = readOneInt(); int b3 = readOneInt(); result = 12481 + (b1 - 241) * 65536 + b2 * 256 + b3; } else { throw new RuntimeException("Invalid varint length indicator"); } return result; } public int size() { return size; } public boolean end(Integer customEnd) { return cursor >= size || customEnd != null && cursor >= customEnd; } }