| 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. |
| 4 | module asn1 |
| 5 | |
| 6 | // base128_int_length calculates the length of bytes needed to store |
| 7 | // integer v encoded in base 128 |
| 8 | fn 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. |
| 25 | fn 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. |
| 43 | fn 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 | |