forked from JesseCoretta/go-objectid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
nanf.go
227 lines (195 loc) · 5.11 KB
/
nanf.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
package objectid
import "math/big"
/*
nanf.go deals with NameAndNumberForm syntax and viability
*/
/*
NameAndNumberForm contains either an identifier with a parenthesis-enclosed
decimal value, or a decimal value alone. An ordered sequence of instances of
this type comprise an instance of [ASN1Notation].
*/
type NameAndNumberForm struct {
identifier string
primaryIdentifier NumberForm
parsed bool
}
/*
IsZero returns a Boolean valu indicative of whether
the receiver is considered nil.
*/
func (r NameAndNumberForm) IsZero() bool {
return !r.parsed
}
/*
Identifier returns the string-based nameForm
value assigned to the receiver instance.
*/
func (r NameAndNumberForm) Identifier() string {
return r.identifier
}
/*
NumberForm returns the underlying [NumberForm]
value assigned to the receiver instance.
*/
func (r NameAndNumberForm) NumberForm() NumberForm {
return r.primaryIdentifier
}
/*
String is a stringer method that returns the properly
formatted [NameAndNumberForm] string value.
*/
func (r NameAndNumberForm) String() (val string) {
n := r.primaryIdentifier.String()
if len(r.identifier) == 0 {
return n
}
return sprintf("%s(%s)", r.identifier, n)
}
/*
Equal returns a Boolean value indicative of whether instance
n of [NameAndNumberForm] matches the receiver.
*/
func (r NameAndNumberForm) Equal(n any) (is bool) {
switch tv := n.(type) {
case NameAndNumberForm:
is = r.identifier == tv.identifier &&
r.primaryIdentifier.Equal(tv.primaryIdentifier)
case *NameAndNumberForm:
is = r.identifier == tv.identifier &&
r.primaryIdentifier.Equal(tv.primaryIdentifier)
}
return
}
func parseRootNameOnly(x string) (r *NameAndNumberForm, err error) {
var root *big.Int
switch x {
case `itu-t`:
root = big.NewInt(0)
case `iso`:
root = big.NewInt(1)
case `joint-iso-itu-t`:
root = big.NewInt(2)
default:
err = errorf("Unknown root abbreviation, or no closing NumberForm parenthesis to read")
}
if err == nil {
r = &NameAndNumberForm{
parsed: true,
identifier: x,
primaryIdentifier: NumberForm(*root),
}
}
return
}
/*
parseNaNFstr returns an instance of *[NameAndNumberForm] alongside an error.
*/
func parseNaNFstr(x string) (r *NameAndNumberForm, err error) {
// Don't waste time on bogus values.
if len(x) == 0 {
err = errorf("No content for parseNaNFstr to read")
return
} else if x[len(x)-1] != ')' {
r, err = parseRootNameOnly(x)
return
}
// index the rune for '(', indicating the
// identifier (nameForm) has ended, and the
// numberForm is beginning.
idx := indexRune(x, '(')
if idx == -1 {
err = errorf("No opening parenthesis for parseNaNFstr to read")
return
}
// select the numerical characters,
// or bail out ...
n := x[idx+1 : len(x)-1]
if !isNumber(n) {
err = errorf("Bad numberForm")
return
}
// Parse/verify what appears to be the
// identifier string value.
var identifier string = x[:idx]
if !isIdentifier(identifier) {
err = errorf("Invalid identifier [%s]; syntax must conform to: LOWER *[ [-] +[ UPPER / LOWER / DIGIT ] ]", identifier)
return
}
// parse the string numberForm value into
// an instance of NumberForm, or bail out.
var prid NumberForm
if prid, err = NewNumberForm(n); err == nil {
// Prepare to return valid information.
r = new(NameAndNumberForm)
r.parsed = true
r.primaryIdentifier = prid
r.identifier = x[:idx]
}
return
}
func parseNaNFOrNF(tv string) (r *NameAndNumberForm, err error) {
r = new(NameAndNumberForm)
if !isNumber(tv) {
r, err = parseNaNFstr(tv)
} else {
var a NumberForm
if a, err = NewNumberForm(tv); err == nil {
r = &NameAndNumberForm{primaryIdentifier: a}
}
}
return
}
func parseNaNFBig(tv *big.Int) (r *NameAndNumberForm, err error) {
r = new(NameAndNumberForm)
if tv.Int64() < 0 {
err = errorf("NameAndNumberForm cannot contain a negative NumberForm")
return
}
if len(tv.Bytes()) == 0 {
err = errorf("NumberForm (%T) is nil", tv)
return
}
r.primaryIdentifier = NumberForm(*tv)
return
}
/*
NewNameAndNumberForm returns an instance of *[NameAndNumberForm]
alongside an error. Valid input forms are:
• nameAndNumberForm (e.g.: "enterprise(1)"), or ...
• numberForm (e.g.: 1)
[NumberForm] components CANNOT be negative. Permitted input types are
string, uint, uint64, [NumberForm], *[math/big.Int] and (non-negative) int.
*/
func NewNameAndNumberForm(x any) (r *NameAndNumberForm, err error) {
switch tv := x.(type) {
case string:
r, err = parseNaNFOrNF(tv)
case *big.Int:
r, err = parseNaNFBig(tv)
case NumberForm:
r = new(NameAndNumberForm)
r.primaryIdentifier = tv
case uint64:
u, _ := NewNumberForm(tv) // skip error checking, we know it won't overflow.
r = new(NameAndNumberForm)
r.primaryIdentifier = u
case uint:
r = new(NameAndNumberForm)
r, err = NewNameAndNumberForm(uint64(tv))
case int:
r = new(NameAndNumberForm)
if tv < 0 {
err = errorf("NumberForm cannot be negative")
break
}
r, err = NewNameAndNumberForm(uint64(tv))
default:
err = errorf("Unsupported %T input type '%T'", r, tv)
}
// mark this instance as complete,
// assuming no errors were found.
if err == nil {
r.parsed = true
}
return
}