View Javadoc
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  }