v/vlib/x/encoding/asn1/base128.v

68 lines
1.3 KiB
V

// Copyright (c) 2022, 2024 blackshirt. All rights reserved.
// Use of this source code is governed by a MIT License
// that can be found in the LICENSE file.
module asn1
// base128_int_length calculates the length of bytes needed to store
// integer v encoded in base 128
fn base128_int_length(v i64) int {
if v == 0 {
return 1
}
mut n := v
mut ret := 0
for n > 0 {
ret += 1
n >>= 7
}
return ret
}
// encode_base128_int serializes integer to bytes array in base 128 integer.
fn encode_base128_int(mut dst []u8, n i64) []u8 {
l := base128_int_length(n)
for i := l - 1; i >= 0; i-- {
mut o := u8(n >> u32(i * 7))
o &= 0x7f
if i != 0 {
o |= 0x80
}
dst << o
}
return dst
}
// decode_base128_int read bytes as base 128 integer for current position `loc`.
// Its returns integer value and the next offset to read from.
fn decode_base128_int(bytes []u8, loc int) !(int, int) {
mut pos := loc
mut r64 := i64(0)
mut ret := 0
for s := 0; pos < bytes.len; s++ {
r64 <<= 7
b := bytes[pos]
if s == 0 && b == 0x80 {
return error('integer is not minimaly encoded')
}
r64 |= i64(b & 0x7f)
pos += 1
if b & 0x80 == 0 {
ret = int(r64)
if r64 > max_i32 {
return error('base 128 integer too large')
}
return ret, pos
}
}
return error('truncated base 128 integer')
}