v2 / vlib / x / encoding / asn1 / base128.v
67 lines · 55 sloc · 1.3 KB · fdc49dc51a0d7e83abd5b383afaaab3f2793f2cf
Raw
1// Copyright (c) 2022, 2024 blackshirt. All rights reserved.
2// Use of this source code is governed by a MIT License
3// that can be found in the LICENSE file.
4module asn1
5
6// base128_int_length calculates the length of bytes needed to store
7// integer v encoded in base 128
8fn base128_int_length(v i64) int {
9 if v == 0 {
10 return 1
11 }
12
13 mut n := v
14 mut ret := 0
15
16 for n > 0 {
17 ret += 1
18 n >>= 7
19 }
20
21 return ret
22}
23
24// encode_base128_int serializes integer to bytes array in base 128 integer.
25fn encode_base128_int(mut dst []u8, n i64) []u8 {
26 l := base128_int_length(n)
27
28 for i := l - 1; i >= 0; i-- {
29 mut o := u8(n >> u32(i * 7))
30 o &= 0x7f
31 if i != 0 {
32 o |= 0x80
33 }
34
35 dst << o
36 }
37
38 return dst
39}
40
41// decode_base128_int read bytes as base 128 integer for current position `loc`.
42// Its returns integer value and the next offset to read from.
43fn decode_base128_int(bytes []u8, loc int) !(int, int) {
44 mut pos := loc
45 mut r64 := i64(0)
46 mut ret := 0
47 for s := 0; pos < bytes.len; s++ {
48 r64 <<= 7
49 b := bytes[pos]
50
51 if s == 0 && b == 0x80 {
52 return error('integer is not minimaly encoded')
53 }
54
55 r64 |= i64(b & 0x7f)
56 pos += 1
57
58 if b & 0x80 == 0 {
59 ret = int(r64)
60 if r64 > max_i32 {
61 return error('base 128 integer too large')
62 }
63 return ret, pos
64 }
65 }
66 return error('truncated base 128 integer')
67}
68