I am trying to implement a cross platform Leb128 binary encoder/decoder in Haxe, my current reference is in Golang:
// readVarUint reads an unsigned integer of size n defined in https://webassembly.github.io/spec/core/binary/values.html#binary-int
// readVarUint panics if n>64.
func readVarUint(r io.Reader, n uint) (uint64, error) {
if n > 64 {
panic(errors.New("leb128: n must <= 64"))
}
p := make([]byte, 1)
var res uint64
var shift uint
for {
_, err := io.ReadFull(r, p)
if err != nil {
return 0, err
}
b := uint64(p[0])
switch {
case b < 1<<7 && b < 1<<n:
res += (1 << shift) * b
return res, nil
case b >= 1<<7 && n > 7:
res += (1 << shift) * (b - 1<<7)
shift += 7
n -= 7
default:
return 0, errors.New("leb128: invalid uint")
}
}
}
// readVarint reads a signed integer of size n, defined in https://webassembly.github.io/spec/core/binary/values.html#binary-int
// readVarint panics if n>64.
func readVarint(r io.Reader, n uint) (int64, error) {
if n > 64 {
panic(errors.New("leb128: n must <= 64"))
}
p := make([]byte, 1)
var res int64
var shift uint
for {
_, err := io.ReadFull(r, p)
if err != nil {
return 0, err
}
b := int64(p[0])
switch {
case b < 1<<6 && uint64(b) < uint64(1<<(n-1)):
res += (1 << shift) * b
return res, nil
case b >= 1<<6 && b < 1<<7 && uint64(b)+1<<(n-1) >= 1<<7:
res += (1 << shift) * (b - 1<<7)
return res, nil
case b >= 1<<7 && n > 7:
res += (1 << shift) * (b - 1<<7)
shift += 7
n -= 7
default:
return 0, errors.New("leb128: invalid int")
}
}
}
// AppendUleb128 appends v to b using unsigned LEB128 encoding.
func AppendUleb128(b []byte, v uint64) []byte {
for {
c := uint8(v & 0x7f)
v >>= 7
if v != 0 {
c |= 0x80
}
b = append(b, c)
if c&0x80 == 0 {
break
}
}
return b
}
// AppendSleb128 appends v to b using signed LEB128 encoding.
func AppendSleb128(b []byte, v int64) []byte {
for {
c := uint8(v & 0x7f)
s := uint8(v & 0x40)
v >>= 7
if (v != -1 || s == 0) && (v != 0 || s != 0) {
c |= 0x80
}
b = append(b, c)
if c&0x80 == 0 {
break
}
}
return b
}
I would appreciate your suggestions.