v2 / vlib / x / encoding / asn1 / bench / bench.v
108 lines · 95 sloc · 3.57 KB · 2f53e2d219cb0baac31887523366750bfd3c1942
Raw
1import time
2import x.encoding.asn1
3
4// This Benchmark was performs serialization and deserialization from ASN.1 schema defined as:
5// ```asn.1
6// Example ::= SEQUENCE {
7// greeting UTF8String,
8// answer INTEGER,
9// type [1] EXPLICIT OBJECT IDENTIFIER
10// }
11// ```
12struct Example {
13 greeting asn1.Utf8String
14 answer asn1.Integer
15 // you can tag your struct fields with supported options.
16 tipe asn1.ObjectIdentifier @[context_specific: 1; explicit; inner: 6]
17}
18
19fn (ex Example) tag() asn1.Tag {
20 return asn1.default_sequence_tag
21}
22
23// you can build your payload manually or use `asn1.make_payload`, but be aware,
24// if your structure contains generics, its may not work (currently).
25// Updates: Thank to @felipensp. He has a great job to resolve this issue.
26// Its was resolved in [22724](https://github.com/vlang/v/pull/22724)
27fn (ex Example) payload() ![]u8 {
28 kd := asn1.KeyDefault(map[string]asn1.Element{})
29 payload := asn1.make_payload[Example](ex, kd)!
30
31 return payload
32}
33
34// You can write custom decode routines for the Example structure. This is only one
35// example, but its possible to do this in other ways with help from this module such
36// as using the `Parser` codec.
37fn Example.decode(bytes []u8) !Example {
38 // just call raw .decode on bytes
39 // for example, its should produce sequence type.
40 elem := asn1.decode(bytes)!
41 assert elem.tag().equal(asn1.default_sequence_tag) // should true
42
43 // cast produced element into Sequence type and get the fields.
44 seq := elem.into_object[asn1.Sequence]()!
45 fields := seq.fields()
46
47 // and then, turn every field into desired objects based on your schema.
48 // first two field is not wrapped element, so just turn into real object.
49 greeting := fields[0].into_object[asn1.Utf8String]()!
50 answer := fields[1].into_object[asn1.Integer]()!
51
52 // the third field is a context_specific wrapped element, just unwrap it with the
53 // same options used to encode.
54 oid_tipe := fields[2].unwrap_with_options('context_specific:1;explicit; inner:6')!
55 tipe := oid_tipe.into_object[asn1.ObjectIdentifier]()!
56
57 // then build your Example struct
58 ex := Example{
59 greeting: greeting
60 answer: answer
61 tipe: tipe
62 }
63 return ex
64}
65
66fn main() {
67 expected_output := [u8(0x30), 18, u8(12), 5, 72, 101, 108, 108, 111, u8(2), 1, 42, u8(0xA1),
68 6, 6, 4, 43, 6, 1, 3]
69 ex := Example{
70 greeting: asn1.Utf8String.new('Hello')!
71 answer: asn1.Integer.from_int(42)
72 tipe: asn1.ObjectIdentifier.from_ints([1, 3, 6, 1, 3])!
73 }
74 iterations := 1000
75
76 println('Benchmarking ASN.1 encode...')
77 mut total_enc_time := i64(0)
78 for _ in 0 .. iterations {
79 sw := time.new_stopwatch()
80 _ := asn1.encode(ex) or { panic(err) }
81 elapsed := sw.elapsed().microseconds()
82 total_enc_time += elapsed
83 }
84 avg_enc_time := total_enc_time / iterations
85 println('Average example encode time: ${avg_enc_time} µs')
86
87 println('Benchmarking ASN.1 decode (with asn1.decode)...')
88 mut total_dec_time := i64(0)
89 for _ in 0 .. iterations {
90 sw := time.new_stopwatch()
91 _ := asn1.decode(expected_output) or { panic(err) }
92 elapsed := sw.elapsed().microseconds()
93 total_dec_time += elapsed
94 }
95 avg_asn1dec_time := total_dec_time / iterations
96 println('Average (asn1.decode) decode time: ${avg_asn1dec_time} µs')
97
98 println('Benchmarking ASN.1 decode with Example.decode)...')
99 mut total_exdec_time := i64(0)
100 for _ in 0 .. iterations {
101 sw := time.new_stopwatch()
102 _ := asn1.decode(expected_output) or { panic(err) }
103 elapsed := sw.elapsed().microseconds()
104 total_exdec_time += elapsed
105 }
106 avg_exdec_time := total_exdec_time / iterations
107 println('Average (Example.decode) decode time: ${avg_exdec_time} µs')
108}
109