1 // Package varint is a variable integer encoding that works in reverse compared
2 // to the stdlib binary Varint. The terminal byte in the encoding is the one
3 // with the 8th bit set. This is basically like a base 128 encoding. It reads
4 // forward using an io.Reader and writes forward using an io.Writer.
5 package varint
6 7 import (
8 "io"
9 10 "golang.org/x/exp/constraints"
11 "next.orly.dev/pkg/lol/chk"
12 )
13 14 func Encode[V constraints.Integer](w io.Writer, v V) {
15 x := []byte{0}
16 for {
17 x[0] = byte(v) & 127
18 v >>= 7
19 if v == 0 {
20 x[0] |= 128
21 _, _ = w.Write(x)
22 break
23 } else {
24 _, _ = w.Write(x)
25 }
26 }
27 }
28 29 func Decode(r io.Reader) (v uint64, err error) {
30 x := []byte{0}
31 v += uint64(x[0])
32 var i uint64
33 for {
34 if _, err = r.Read(x); chk.E(err) {
35 return
36 }
37 if x[0] >= 128 {
38 v += uint64(x[0]&127) << (i * 7)
39 return
40 } else {
41 v += uint64(x[0]) << (i * 7)
42 i++
43 }
44 }
45 }
46