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 }