v2 / vlib / x / encoding / asn1 / util.v
118 lines · 99 sloc · 2.23 KB · 8e35f4d9848f7ad35d857a187dddbfd2eca5e19d
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// ASN.1 Utility function
7
8// read_bytes was safe version of bytes slicing, `src[pos..pos+size]`
9fn read_bytes(src []u8, pos int, size int) ![]u8 {
10 if src.len < 1 || pos > src.len || size > src.len {
11 return error(' pos=${pos} or size=${size} bigger than len=${src.len}')
12 }
13 if pos + size > src.len {
14 return error('pos + size maybe getting overflow')
15 }
16
17 ret := src[pos..pos + size]
18 return ret
19}
20
21fn read_byte(src []u8, loc int) !(u8, int) {
22 if src.len == 0 || loc + 1 > src.len {
23 return error('invalid loc or len')
24 }
25
26 mut pos := loc
27 result := src[pos]
28 pos += 1
29
30 return result, pos
31}
32
33fn read_digit(src []u8, loc int) !(u8, int) {
34 val, pos := read_byte(src, loc)!
35 // check its a digit, '0'-'9',
36 // aka, 0x30 s/d 0x39 in hex, or 48-57 in dec
37 if !val.is_digit() {
38 return error('not digit byte')
39 }
40
41 digit := val - u8(0x30) // get the digit value
42 return digit, pos
43}
44
45fn read_2_digits(src []u8, loc int) !(u8, int) {
46 if loc >= src.len || src.len < 2 + loc {
47 return error('not enough bytes')
48 }
49 mut val, mut pos := read_digit(src, loc)!
50
51 first := val * 10
52
53 if pos < src.len {
54 val, pos = read_digit(src, pos)!
55 }
56 return first + val, pos
57}
58
59fn read_4_digits(src []u8, loc int) !(u16, int) {
60 if loc >= src.len || src.len < 4 + loc {
61 return error('not enough bytes')
62 }
63 mut val, mut pos := read_digit(src, loc)!
64 first := u16(val) * 1000
65
66 if pos < src.len {
67 val, pos = read_digit(src, pos)!
68 }
69 second := u16(val) * 100
70
71 if pos < src.len {
72 val, pos = read_digit(src, pos)!
73 }
74 third := u16(val) * 10
75
76 if pos < src.len {
77 val, pos = read_digit(src, pos)!
78 }
79 fourth := u16(val)
80
81 result := first + second + third + fourth
82 return result, pos
83}
84
85fn validate_date(year u16, month u8, day u8) bool {
86 if year < 0 {
87 return false
88 }
89 if day < 1 {
90 return false
91 }
92 mut dim := month
93 match month {
94 1, 3, 5, 7, 8, 10, 12 {
95 dim = 31
96 }
97 4, 6, 9, 11 {
98 dim = 30
99 }
100 2 {
101 // kabisat
102 if (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 {
103 dim = 29
104 } else {
105 dim = 28
106 }
107 }
108 else {
109 return false
110 }
111 }
112
113 if day > dim {
114 return false
115 }
116
117 return true
118}
119