1 package edu.jiangxin.apktoolbox.convert.protobuf.unsupervised; 2 3 import org.apache.commons.lang3.ArrayUtils; 4 5 import java.math.BigInteger; 6 import java.nio.ByteOrder; 7 import java.util.Map; 8 9 public class BufferReader { 10 11 private byte[] buffer; 12 private int offset; 13 private int savedOffset; 14 15 public BufferReader(byte[] buffer) { 16 this.buffer = buffer; 17 offset = 0; 18 } 19 20 public int getOffset() { 21 return offset; 22 } 23 24 public BigInteger readVarInt() { 25 Map<String, Object> result = VarintUtils.decodeVarint(buffer, offset); 26 offset += (int) result.get("length"); 27 return (BigInteger) result.get("value"); 28 } 29 30 public byte[] readBuffer(int length) { 31 this.checkByte(length); 32 byte[] result = ArrayUtils.subarray(buffer, offset, offset + length); 33 offset += length; 34 return result; 35 } 36 37 public void trySkipGrpcHeader() { 38 int backupOffset = offset; 39 if (buffer.length > 0 && buffer[offset] == 0 && leftBytes() >= 5) { 40 offset++; 41 int length = ByteUtil.bytesToInt(buffer, offset, ByteOrder.BIG_ENDIAN); 42 offset += 4; 43 44 if (length > leftBytes()) { 45 offset = backupOffset; 46 } 47 } 48 } 49 50 public int leftBytes() { 51 return buffer.length - offset; 52 } 53 54 public void checkByte(int length) { 55 int bytesAvailable = leftBytes(); 56 if (length > bytesAvailable) { 57 throw new RuntimeException("Not enough bytes left. Requested: " + length + " left: " + bytesAvailable); 58 } else if (length < 0) { 59 throw new RuntimeException("The length should be greater than 0"); 60 } 61 } 62 63 public void checkpoint() { 64 this.savedOffset = offset; 65 } 66 67 public void resetToCheckpoint() { 68 offset = this.savedOffset; 69 } 70 71 }