v2 / vlib / x / encoding / asn1 / utf8string.v
103 lines · 87 sloc · 2.61 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
6import encoding.utf8
7
8// default_utf8string_tag is the default tag of ASN.1 UTF8STRING type.
9pub const default_utf8string_tag = Tag{.universal, false, int(TagType.utf8string)}
10
11// ASN.1 UNIVERSAL CLASS OF UTF8STRING TYPE.
12//
13// UTF8STRING is UTF8 unicode charset
14pub struct Utf8String {
15pub:
16 value string
17}
18
19// new creates a new Utf8String element from string s.
20pub fn Utf8String.new(s string) !Utf8String {
21 if !utf8.validate_str(s) {
22 return error('Utf8String: invalid UTF-8 string')
23 }
24 return Utf8String{
25 value: s
26 }
27}
28
29// from_bytes creates a new Utf8String element from bytes in src.
30pub fn Utf8String.from_bytes(src []u8) !Utf8String {
31 if !utf8.validate_str(src.bytestr()) {
32 return error('Utf8String: invalid UTF-8 string')
33 }
34 return Utf8String{
35 value: src.bytestr()
36 }
37}
38
39// tag returns the tag of Utf8String element.
40pub fn (uts Utf8String) tag() Tag {
41 return default_utf8string_tag
42}
43
44// payload returns the payload of Utf8String element.
45pub fn (uts Utf8String) payload() ![]u8 {
46 return uts.payload_with_rule(.der)!
47}
48
49fn (uts Utf8String) str() string {
50 if uts.value.len == 0 {
51 return 'Utf8String (<empty>)'
52 }
53 return 'Utf8String (${uts.value})'
54}
55
56fn (uts Utf8String) payload_with_rule(rule EncodingRule) ![]u8 {
57 if rule != .der && rule != .ber {
58 return error('Utf8String: Unsupported rule')
59 }
60 if !utf8.validate_str(uts.value) {
61 return error('Utf8String: invalid UTF-8 string')
62 }
63 return uts.value.bytes()
64}
65
66fn Utf8String.parse(mut p Parser) !Utf8String {
67 tag := p.read_tag()!
68 if !tag.equal(default_utf8string_tag) {
69 return error('Bad Utf8String tag')
70 }
71 length := p.read_length()!
72 bytes := p.read_bytes(length)!
73
74 res := Utf8String.from_bytes(bytes)!
75
76 return res
77}
78
79fn Utf8String.decode(src []u8) !(Utf8String, int) {
80 return Utf8String.decode_with_rule(src, .der)!
81}
82
83fn Utf8String.decode_with_rule(bytes []u8, rule EncodingRule) !(Utf8String, int) {
84 tag, length_pos := Tag.decode_with_rule(bytes, 0, rule)!
85 if !tag.equal(default_utf8string_tag) {
86 return error('Unexpected non-utf8string tag')
87 }
88 length, content_pos := Length.decode_with_rule(bytes, length_pos, rule)!
89 content := if length == 0 {
90 []u8{}
91 } else {
92 // non-null length should contains non-null bytes
93 if content_pos >= bytes.len || content_pos + length > bytes.len {
94 return error('Utf8String: truncated payload bytes')
95 }
96 unsafe { bytes[content_pos..content_pos + length] }
97 }
98
99 ust := Utf8String.from_bytes(content)!
100 next := content_pos + length
101
102 return ust, next
103}
104