varint.mx raw

   1  // Package varint is a variable integer encoding with terminal byte having 8th bit set.
   2  package varint
   3  
   4  import (
   5  	"io"
   6  
   7  	"smesh.lol/pkg/lol/chk"
   8  )
   9  
  10  type Integer interface {
  11  	~int | ~int8 | ~int16 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint64
  12  }
  13  
  14  func Encode[V 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