v2 / vlib / x / encoding / asn1 / visiblestring.v
104 lines · 87 sloc · 2.73 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
6// default_visiblestring_tag is the default tag of ASN.1 VISIBLESTRING type.
7pub const default_visiblestring_tag = Tag{.universal, false, int(TagType.visiblestring)}
8
9// ASN.1 UNIVERSAL CLASS OF VISIBLESTRING TYPE.
10//
11// The ASN.1 VisibleString type supports a subset of ASCII characters that does not include control characters.
12pub struct VisibleString {
13pub:
14 value string
15}
16
17// from_string creates a new VisibleString from string s.
18pub fn VisibleString.new(s string) !VisibleString {
19 if contains_ctrl_chars(s.bytes()) {
20 return error('VisibleString: contains control chars')
21 }
22 return VisibleString{
23 value: s
24 }
25}
26
27// from_bytes creates a new VisibleString from bytes src
28fn VisibleString.from_bytes(src []u8) !VisibleString {
29 if contains_ctrl_chars(src) {
30 return error('VisibleString: contains control chars')
31 }
32 return VisibleString{
33 value: src.bytestr()
34 }
35}
36
37// tag returns the tag of VisibleString type element.
38pub fn (vst VisibleString) tag() Tag {
39 return default_visiblestring_tag
40}
41
42// payload returns the payload of VisibleString type element.
43pub fn (vst VisibleString) payload() ![]u8 {
44 if contains_ctrl_chars(vst.value.bytes()) {
45 return error('VisibleString: contains control chars')
46 }
47 return vst.value.bytes()
48}
49
50fn (vst VisibleString) str() string {
51 if vst.value.len == 0 {
52 return 'VisibleString (<empty>)'
53 }
54 return 'VisibleString (${vst.value})'
55}
56
57fn VisibleString.parse(mut p Parser) !VisibleString {
58 tag := p.read_tag()!
59 if !tag.equal(default_visiblestring_tag) {
60 return error('Bad VisibleString tag')
61 }
62 length := p.read_length()!
63 bytes := p.read_bytes(length)!
64
65 res := VisibleString.from_bytes(bytes)!
66
67 return res
68}
69
70fn VisibleString.decode(src []u8) !(VisibleString, int) {
71 return VisibleString.decode_with_rule(src, .der)!
72}
73
74fn VisibleString.decode_with_rule(bytes []u8, rule EncodingRule) !(VisibleString, int) {
75 tag, length_pos := Tag.decode_with_rule(bytes, 0, rule)!
76 if !tag.equal(default_visiblestring_tag) {
77 return error('Unexpected non-visiblestring tag')
78 }
79 length, content_pos := Length.decode_with_rule(bytes, length_pos, rule)!
80 content := if length == 0 {
81 []u8{}
82 } else {
83 if content_pos >= bytes.len || content_pos + length > bytes.len {
84 return error('VisibleString: truncated payload bytes')
85 }
86 unsafe { bytes[content_pos..content_pos + length] }
87 }
88
89 vst := VisibleString.from_bytes(content)!
90 next := content_pos + length
91
92 return vst, next
93}
94
95// Utility function for VisibleString
96//
97
98fn is_ctrl_char(c u8) bool {
99 return (c >= 0 && c <= 0x1f) || c == 0x7f
100}
101
102fn contains_ctrl_chars(src []u8) bool {
103 return src.any(is_ctrl_char(it))
104}
105