| 39 | } |
| 40 | |
| 41 | func readVarInt(r *bufio.Reader, sz int, v *int64) (remain int, err error) { |
| 42 | // Optimistically assume that most of the time, there will be data buffered |
| 43 | // in the reader. If this is not the case, the buffer will be refilled after |
| 44 | // consuming zero bytes from the input. |
| 45 | input, _ := r.Peek(r.Buffered()) |
| 46 | x := uint64(0) |
| 47 | s := uint(0) |
| 48 | |
| 49 | for { |
| 50 | if len(input) > sz { |
| 51 | input = input[:sz] |
| 52 | } |
| 53 | |
| 54 | for i, b := range input { |
| 55 | if b < 0x80 { |
| 56 | x |= uint64(b) << s |
| 57 | *v = int64(x>>1) ^ -(int64(x) & 1) |
| 58 | n, err := r.Discard(i + 1) |
| 59 | return sz - n, err |
| 60 | } |
| 61 | |
| 62 | x |= uint64(b&0x7f) << s |
| 63 | s += 7 |
| 64 | } |
| 65 | |
| 66 | // Make room in the input buffer to load more data from the underlying |
| 67 | // stream. The x and s variables are left untouched, ensuring that the |
| 68 | // varint decoding can continue on the next loop iteration. |
| 69 | n, _ := r.Discard(len(input)) |
| 70 | sz -= n |
| 71 | if sz == 0 { |
| 72 | return 0, errShortRead |
| 73 | } |
| 74 | |
| 75 | // Fill the buffer: ask for one more byte, but in practice the reader |
| 76 | // will load way more from the underlying stream. |
| 77 | if _, err := r.Peek(1); err != nil { |
| 78 | if errors.Is(err, io.EOF) { |
| 79 | err = errShortRead |
| 80 | } |
| 81 | return sz, err |
| 82 | } |
| 83 | |
| 84 | // Grab as many bytes as possible from the buffer, then go on to the |
| 85 | // next loop iteration which is going to consume it. |
| 86 | input, _ = r.Peek(r.Buffered()) |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | func readBool(r *bufio.Reader, sz int, v *bool) (int, error) { |
| 91 | return peekRead(r, sz, 1, func(b []byte) { *v = b[0] != 0 }) |