decode.go
1 package codec 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "math" 7 ) 8 9 type Decoder struct { 10 buf []byte 11 pos int // current (unread) byte position 12 } 13 14 func Decode(b []byte) *Decoder { 15 return &Decoder{buf: b} 16 } 17 18 func (d *Decoder) Has(n int) bool { 19 return d.pos+n <= len(d.buf) 20 } 21 22 func (d *Decoder) Bytes(num int) []byte { 23 p := d.pos 24 d.pos += num 25 return d.buf[p : p+num] 26 } 27 28 // All remaining bytes in the buffer 29 func (d *Decoder) Rest() []byte { 30 p := d.pos 31 d.pos = len(d.buf) 32 return d.buf[p:] 33 } 34 35 func (d *Decoder) Bool() bool { 36 v := d.buf[d.pos] 37 d.pos += 1 38 return v != 0 39 } 40 41 func (d *Decoder) UInt8() uint8 { 42 p := d.pos 43 d.pos += 1 44 return d.buf[p] 45 } 46 47 func (d *Decoder) UInt16le() uint16 { 48 p := d.pos 49 d.pos += 2 50 return binary.LittleEndian.Uint16(d.buf[p : p+2]) 51 } 52 53 func (d *Decoder) UInt16be() uint16 { 54 p := d.pos 55 d.pos += 2 56 return binary.BigEndian.Uint16(d.buf[p : p+2]) 57 } 58 59 func (d *Decoder) UInt32le() uint32 { 60 p := d.pos 61 d.pos += 4 62 return binary.LittleEndian.Uint32(d.buf[p : p+4]) 63 } 64 65 func (d *Decoder) UInt32be() uint32 { 66 p := d.pos 67 d.pos += 4 68 return binary.BigEndian.Uint32(d.buf[p : p+4]) 69 } 70 71 func (d *Decoder) UInt64le() uint64 { 72 p := d.pos 73 d.pos += 8 74 return binary.LittleEndian.Uint64(d.buf[p : p+8]) 75 } 76 77 func (d *Decoder) Int64le() int64 { 78 p := d.pos 79 d.pos += 8 80 return int64(binary.LittleEndian.Uint64(d.buf[p : p+8])) 81 } 82 func (d *Decoder) VarUInt() uint64 { 83 val := d.buf[d.pos] 84 d.pos += 1 85 if val < 253 { 86 return uint64(val) 87 } 88 if val == 253 { 89 return uint64(d.UInt16le()) 90 } 91 if val == 254 { 92 return uint64(d.UInt32le()) 93 } 94 return d.UInt64le() 95 } 96 97 func (d *Decoder) VarString() string { 98 len := d.VarUInt() 99 if len > math.MaxInt { 100 panic(fmt.Sprintf("decoded string length too long (greater than max-int): %v", len)) 101 } 102 data := d.Bytes(int(len)) 103 return string(data) 104 } 105 106 func (d *Decoder) PadString(size int) string { 107 data := d.Bytes(size) 108 if size > 0 { 109 end := size - 1 110 for data[end] == 0 && end > 0 { 111 end-- 112 } 113 return string(data[:end+1]) 114 } 115 return "" 116 }