v2 / vlib / x / encoding / asn1 / optional.v
79 lines · 70 sloc · 2.46 KB · 3d60410b605d001e54f280070d5f952da9de1112
Raw
1module asn1
2
3// ASN.1 OPTIONAL Element.
4//
5// note: At the abstract ASN.1 level the absence of a DEFAULT value in an encoding is the same as its being present.
6// Contrast this with OPTIONAL, where a value being present in the encoding is semantically distinct from its being absent.
7// In some encoding rules (like BER/PER) it is at the whim of the sender whether a DEFAULT value is encoded or not
8// (except for primitive type values in PER which are required by the PER standard to be absent in the encoding),
9// while with others (like DER) the DEFAULT value is NEVER encoded. For all encoding rules,
10// if the component that has a DEFAULT value is not encoded the receiving application must behave as though the DEFAULT value had been encoded.
11pub struct Optional {
12 // underlying element marked as an optional
13 elem Element
14mut:
15 // presence of this flag negates optionality of this elemeent.
16 // set to true when its should present, if not sure, just set to to false
17 present bool
18}
19
20// new creates and marked element as an Optional element.
21pub fn Optional.new(el Element, with_present bool) !Optional {
22 if el is Optional {
23 return error('recursive optional is not allowed')
24 }
25 return Optional{
26 elem: el
27 present: with_present
28 }
29}
30
31// set_present_bit sets this Optional element with flag in present.
32pub fn (mut opt Optional) set_present_bit(present bool) {
33 opt.present = present
34}
35
36// tag returns the tag of Optional element.
37pub fn (opt Optional) tag() Tag {
38 return opt.elem.tag()
39}
40
41// payload the payload of Optional element.
42pub fn (opt Optional) payload() ![]u8 {
43 return opt.elem.payload()!
44}
45
46// encode serializes this Optional element into bytes array.
47pub fn (opt Optional) encode() ![]u8 {
48 return opt.encode_with_rule(.der)!
49}
50
51fn (opt Optional) encode_with_rule(_rule EncodingRule) ![]u8 {
52 if opt.present {
53 // elem := opt.into_element()!
54 return encode_with_rule(opt, .der)!
55 }
56 // not present
57 return []u8{}
58}
59
60// into_element turns this optional into Element.
61pub fn (opt Optional) into_element() !Element {
62 return parse_element(opt.tag(), opt.payload()!)!
63}
64
65// into_object tries to turns this optional into real underlying object T.
66// Its return object T on success or error on fails.
67pub fn (opt Optional) into_object[T]() !T {
68 $if T !is Element {
69 return error('T is not element')
70 }
71 $if T is Optional {
72 return error('T is optional')
73 }
74 elem := opt.into_element()!
75 if elem is Optional {
76 return error('elem is also optional')
77 }
78 return elem.into_object[T]()!
79}
80