-
Notifications
You must be signed in to change notification settings - Fork 0
/
dstr.go
131 lines (108 loc) · 3.7 KB
/
dstr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package dirsyn
/*
DirectoryString implements the Directory String syntax.
From [§ 3.3.6 of RFC 4517]:
DirectoryString = 1*UTF8
From [§ 1.4 of RFC 4512]:
UTF8 = UTF1 / UTFMB
UTFMB = UTF2 / UTF3 / UTF4
UTF0 = %x80-BF
UTF1 = %x00-7F
UTF2 = %xC2-DF UTF0
UTF3 = %xE0 %xA0-BF UTF0 / %xE1-EC 2(UTF0) /
%xED %x80-9F UTF0 / %xEE-EF 2(UTF0)
UTF4 = %xF0 %x90-BF 2(UTF0) / %xF1-F3 3(UTF0) /
%xF4 %x80-8F 2(UTF0)
From [ITU-T Rec. X.520 clause 2.6]:
UnboundedDirectoryString ::= CHOICE {
teletexString TeletexString(SIZE (1..MAX)),
printableString PrintableString(SIZE (1..MAX)),
bmpString BMPString(SIZE (1..MAX)),
universalString UniversalString(SIZE (1..MAX)),
uTF8String UTF8String(SIZE (1..MAX)) }
DirectoryString{INTEGER:maxSize} ::= CHOICE {
teletexString TeletexString(SIZE (1..maxSize,...)),
printableString PrintableString(SIZE (1..maxSize,...)),
bmpString BMPString(SIZE (1..maxSize,...)),
universalString UniversalString(SIZE (1..maxSize,...)),
uTF8String UTF8String(SIZE (1..maxSize,...)) }
[§ 1.4 of RFC 4512]: https://datatracker.ietf.org/doc/html/rfc4512#section-1.4
[§ 3.3.6 of RFC 4517]: https://datatracker.ietf.org/doc/html/rfc4517#section-3.3.6
[ITU-T Rec. X.520 clause 2.6]: https://www.itu.int/rec/T-REC-X.520
*/
type DirectoryString interface {
String() string
Choice() string
IsZero() bool
isDirectoryString() // differentiate from other interfaces
}
func (r BMPString) isDirectoryString() {}
func (r UTF8String) isDirectoryString() {}
func (r UniversalString) isDirectoryString() {}
func (r TeletexString) isDirectoryString() {}
func (r PrintableString) isDirectoryString() {}
func (r BMPString) Choice() string { return `bmpString` }
func (r UTF8String) Choice() string { return `utf8String` }
func (r UniversalString) Choice() string { return `universalString` }
func (r TeletexString) Choice() string { return `teletexString` }
func (r PrintableString) Choice() string { return `printableString` }
/*
DirectoryString returns an instance of [DirectoryString] alongside an error.
The following input types are accepted:
- string (parsed as [UTF8String])
- [UTF8String]
- [PrintableString]
- [TeletexString]
- [BMPString]
*/
func (r RFC4517) DirectoryString(x any) (DirectoryString, error) {
return marshalDirectoryString(x)
}
func directoryString(x any) (result Boolean) {
_, err := marshalDirectoryString(x)
result.Set(err == nil)
return
}
func marshalDirectoryString(x any) (ds DirectoryString, err error) {
switch tv := x.(type) {
case UTF8String, string, []byte:
ds, err = assertUTF8String(tv)
case PrintableString:
ds, err = marshalPrintableString(tv)
case UniversalString:
ds, err = marshalUniversalString(tv)
case BMPString:
ds, err = assertBMPString(tv)
case TeletexString:
ds, err = marshalTeletexString(tv)
default:
err = errorBadType("Directory String")
}
return ds, err
}
/*
directoryStringFirstComponentMatch implements [§ 4.2.15 of RFC 4517].
OID: 2.5.13.31
[§ 4.2.15 of RFC 4517]: https://datatracker.ietf.org/doc/html/rfc4517#section-4.2.15
*/
func directoryStringFirstComponentMatch(a, b any) (result Boolean, err error) {
// Use reflection to handle the attribute value.
// This value MUST be a struct (SEQUENCE).
realValue := assertFirstStructField(a)
if realValue == nil {
result.Set(false)
return
}
var field DirectoryString
if field, err = marshalDirectoryString(realValue); err == nil {
var ds DirectoryString
if assertValue := assertFirstStructField(b); assertValue == nil {
ds, err = marshalDirectoryString(b)
result.Set(streq(field.String(), ds.String()))
} else {
ds, err = marshalDirectoryString(assertValue)
result.Set(streq(field.String(), ds.String()))
}
}
return
}