v2 / vlib / x / encoding / asn1 / examples / examples3.v
88 lines · 73 sloc · 2.69 KB · 58fc4dead559901cad648fb695f31d0f6de9945a
Raw
1module main
2
3import x.encoding.asn1
4
5// This example of encode a sequence containing a UTF-8 string, an integer
6// and an explicitly tagged object identifier, conforming to the following
7// ASN.1 schema specification:
8
9// ```asn.1
10// Example ::= SEQUENCE {
11// greeting UTF8String,
12// answer INTEGER,
13// type [1] EXPLICIT OBJECT IDENTIFIER
14// }
15// ```
16
17// You can represent above structure with related structure in `v`, similar like:
18
19struct Example {
20 greeting asn1.Utf8String
21 answer asn1.Integer
22 // you can tag your struct fields with supported options.
23 tipe asn1.ObjectIdentifier @[context_specific: 1; explicit; inner: 6]
24}
25
26fn (ex Example) tag() asn1.Tag {
27 return asn1.default_sequence_tag
28}
29
30// you can build your payload manually or use `asn1.make_payload`, but with aware,
31// if your structure contains generic, its maybe not work (currently).
32fn (ex Example) payload() ![]u8 {
33 kd := asn1.KeyDefault(map[string]asn1.Element{})
34 payload := asn1.make_payload[Example](ex, kd)!
35 return payload
36}
37
38// You can write routines for deserialize Example structure. This is only examples way,
39// but its possible to use other way with the help from this module, like use
40// `Parser` codec.
41fn Example.decode(bytes []u8) !Example {
42 // just call raw .decode on bytes
43 // by example, its should produce sequence type.
44 elem := asn1.decode(bytes)!
45 assert elem.tag().equal(asn1.default_sequence_tag) // should true
46
47 // cast produced element into Sequence type and get the fields.
48 seq := elem.into_object[asn1.Sequence]()!
49 fields := seq.fields()
50
51 // and then, turn every field into desired object based your schema.
52 // first two field is not wrapped element, so just turn into real object
53 greeting := fields[0].into_object[asn1.Utf8String]()!
54 answer := fields[1].into_object[asn1.Integer]()!
55
56 // the third field is context_specific wrapped element, just unwrap it with the
57 // same options used to encode
58 oid_tipe := fields[2].unwrap_with_options('context_specific:1;explicit; inner:6')!
59 tipe := oid_tipe.into_object[asn1.ObjectIdentifier]()!
60
61 // then build your Example structure
62 ex := Example{
63 greeting: greeting
64 answer: answer
65 tipe: tipe
66 }
67 return ex
68}
69
70fn main() {
71 expected_output := [u8(0x30), 18, u8(12), 5, 72, 101, 108, 108, 111, u8(2), 1, 42, u8(0xA1),
72 6, 6, 4, 43, 6, 1, 3]
73 ex := Example{
74 greeting: asn1.Utf8String.new('Hello')!
75 answer: asn1.Integer.from_int(42)
76 tipe: asn1.ObjectIdentifier.new('1.3.6.1.3')!
77 }
78
79 // serialize the Example object
80 out := asn1.encode(ex)!
81 assert out == expected_output
82
83 // test with data
84 example_obj := Example.decode(out)!
85 dump(ex.greeting == example_obj.greeting)
86 dump(ex.answer == example_obj.answer)
87 dump(ex.tipe == example_obj.tipe)
88}
89