github.com/safing/portbase@v0.19.5/formats/varint/varint.go (about) 1 package varint 2 3 import ( 4 "encoding/binary" 5 "errors" 6 ) 7 8 // ErrBufTooSmall is returned when there is not enough data for parsing a varint. 9 var ErrBufTooSmall = errors.New("varint: buf too small") 10 11 // Pack8 packs a uint8 into a VarInt. 12 func Pack8(n uint8) []byte { 13 if n < 128 { 14 return []byte{n} 15 } 16 return []byte{n, 0x01} 17 } 18 19 // Pack16 packs a uint16 into a VarInt. 20 func Pack16(n uint16) []byte { 21 buf := make([]byte, 3) 22 w := binary.PutUvarint(buf, uint64(n)) 23 return buf[:w] 24 } 25 26 // Pack32 packs a uint32 into a VarInt. 27 func Pack32(n uint32) []byte { 28 buf := make([]byte, 5) 29 w := binary.PutUvarint(buf, uint64(n)) 30 return buf[:w] 31 } 32 33 // Pack64 packs a uint64 into a VarInt. 34 func Pack64(n uint64) []byte { 35 buf := make([]byte, 10) 36 w := binary.PutUvarint(buf, n) 37 return buf[:w] 38 } 39 40 // Unpack8 unpacks a VarInt into a uint8. It returns the extracted int, how many bytes were used and an error. 41 func Unpack8(blob []byte) (uint8, int, error) { 42 if len(blob) < 1 { 43 return 0, 0, ErrBufTooSmall 44 } 45 if blob[0] < 128 { 46 return blob[0], 1, nil 47 } 48 if len(blob) < 2 { 49 return 0, 0, ErrBufTooSmall 50 } 51 if blob[1] != 0x01 { 52 return 0, 0, errors.New("varint: encoded integer greater than 255 (uint8)") 53 } 54 return blob[0], 1, nil 55 } 56 57 // Unpack16 unpacks a VarInt into a uint16. It returns the extracted int, how many bytes were used and an error. 58 func Unpack16(blob []byte) (uint16, int, error) { 59 n, r := binary.Uvarint(blob) 60 if r == 0 { 61 return 0, 0, ErrBufTooSmall 62 } 63 if r < 0 { 64 return 0, 0, errors.New("varint: encoded integer greater than 18446744073709551615 (uint64)") 65 } 66 if n > 65535 { 67 return 0, 0, errors.New("varint: encoded integer greater than 65535 (uint16)") 68 } 69 return uint16(n), r, nil 70 } 71 72 // Unpack32 unpacks a VarInt into a uint32. It returns the extracted int, how many bytes were used and an error. 73 func Unpack32(blob []byte) (uint32, int, error) { 74 n, r := binary.Uvarint(blob) 75 if r == 0 { 76 return 0, 0, ErrBufTooSmall 77 } 78 if r < 0 { 79 return 0, 0, errors.New("varint: encoded integer greater than 18446744073709551615 (uint64)") 80 } 81 if n > 4294967295 { 82 return 0, 0, errors.New("varint: encoded integer greater than 4294967295 (uint32)") 83 } 84 return uint32(n), r, nil 85 } 86 87 // Unpack64 unpacks a VarInt into a uint64. It returns the extracted int, how many bytes were used and an error. 88 func Unpack64(blob []byte) (uint64, int, error) { 89 n, r := binary.Uvarint(blob) 90 if r == 0 { 91 return 0, 0, ErrBufTooSmall 92 } 93 if r < 0 { 94 return 0, 0, errors.New("varint: encoded integer greater than 18446744073709551615 (uint64)") 95 } 96 return n, r, nil 97 }