1package base64vlq 2 3import "io" 4 5const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 6 7const ( 8 vlqBaseShift = 5 9 vlqBase = 1 << vlqBaseShift 10 vlqBaseMask = vlqBase - 1 11 vlqSignBit = 1 12 vlqContinuationBit = vlqBase 13) 14 15var decodeMap [256]byte 16 17func init() { 18 for i := 0; i < len(encodeStd); i++ { 19 decodeMap[encodeStd[i]] = byte(i) 20 } 21} 22 23func toVLQSigned(n int32) int32 { 24 if n < 0 { 25 return -n<<1 + 1 26 } 27 return n << 1 28} 29 30func fromVLQSigned(n int32) int32 { 31 isNeg := n&vlqSignBit != 0 32 n >>= 1 33 if isNeg { 34 return -n 35 } 36 return n 37} 38 39type Encoder struct { 40 w io.ByteWriter 41} 42 43func NewEncoder(w io.ByteWriter) *Encoder { 44 return &Encoder{ 45 w: w, 46 } 47} 48 49func (enc Encoder) Encode(n int32) error { 50 n = toVLQSigned(n) 51 for digit := int32(vlqContinuationBit); digit&vlqContinuationBit != 0; { 52 digit = n & vlqBaseMask 53 n >>= vlqBaseShift 54 if n > 0 { 55 digit |= vlqContinuationBit 56 } 57 58 err := enc.w.WriteByte(encodeStd[digit]) 59 if err != nil { 60 return err 61 } 62 } 63 return nil 64} 65 66type Decoder struct { 67 r io.ByteReader 68} 69 70func NewDecoder(r io.ByteReader) Decoder { 71 return Decoder{ 72 r: r, 73 } 74} 75 76func (dec Decoder) Decode() (n int32, err error) { 77 shift := uint(0) 78 for continuation := true; continuation; { 79 c, err := dec.r.ReadByte() 80 if err != nil { 81 return 0, err 82 } 83 84 c = decodeMap[c] 85 continuation = c&vlqContinuationBit != 0 86 n += int32(c&vlqBaseMask) << shift 87 shift += vlqBaseShift 88 } 89 return fromVLQSigned(n), nil 90} 91