v2 / vlib / x / encoding / asn1 / choices.v
80 lines · 72 sloc · 1.82 KB · 897ec51480ee51714f03534117f603eb28dae7fa
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
6const max_choices_size = 255
7const default_choices_size = 64
8
9// ASN.1 CHOICE
10//
11// Choice is an ASN.1 Element
12pub struct Choice {
13mut:
14 size int = default_choices_size
15 choosen Element
16 choices []Element
17}
18
19// new creates a new choice element. It accepts el as a choosen element
20// and choices as a source of possible choices list.
21pub fn Choice.new(el Element, choices []Element) !Choice {
22 c := Choice{
23 choosen: el
24 choices: choices
25 }
26 c.check()!
27 return c
28}
29
30// set_size sets the maximal this choices size
31pub fn (mut c Choice) set_size(size int) ! {
32 if size > max_choices_size {
33 return error('Your size exceed max_choices_size')
34 }
35 c.size = size
36 c.check()!
37}
38
39// choose chooses some element for as a choosen element for the choice c.
40pub fn (mut c Choice) choose(some Element) ! {
41 mut within := false
42 for el in c.choices {
43 if el.equal(some) {
44 within = true
45 }
46 }
47 if within {
48 c.choosen = some
49 return
50 }
51 return error('element not within choices')
52}
53
54fn (c Choice) check() ! {
55 if c.choices.len == 0 {
56 return error('bad choices list')
57 }
58 if c.choices.len > c.size {
59 return error('Your choices list exceed size')
60 }
61 // check the choosen element is within choices
62 filtered := c.choices.filter(it.equal(c.choosen))
63 // nothing found, so..its bad choice
64 if filtered.len == 0 {
65 return error('choosen element not within choices list')
66 }
67 if filtered.len > 1 {
68 return error('multiples element within choices matching with choosen element')
69 }
70}
71
72// tag returns the tag of choice element.
73pub fn (c Choice) tag() Tag {
74 return c.choosen.tag()
75}
76
77// payload returns the payload of choice element.
78pub fn (c Choice) payload() ![]u8 {
79 return c.choosen.payload()!
80}
81