1
2
3
4
5 package asn1
6
7 import (
8 "reflect"
9 "strconv"
10 "strings"
11 )
12
13
14
15
16
17
18
19
20
21
22 const (
23 TagBoolean = 1
24 TagInteger = 2
25 TagBitString = 3
26 TagOctetString = 4
27 TagNull = 5
28 TagOID = 6
29 TagEnum = 10
30 TagUTF8String = 12
31 TagSequence = 16
32 TagSet = 17
33 TagNumericString = 18
34 TagPrintableString = 19
35 TagT61String = 20
36 TagIA5String = 22
37 TagUTCTime = 23
38 TagGeneralizedTime = 24
39 TagGeneralString = 27
40 )
41
42
43 const (
44 ClassUniversal = 0
45 ClassApplication = 1
46 ClassContextSpecific = 2
47 ClassPrivate = 3
48 )
49
50 type tagAndLength struct {
51 class, tag, length int
52 isCompound bool
53 }
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 type fieldParameters struct {
75 optional bool
76 explicit bool
77 application bool
78 defaultValue *int64
79 tag *int
80 stringType int
81 timeType int
82 set bool
83 omitEmpty bool
84
85
86
87 }
88
89
90
91
92 func parseFieldParameters(str string) (ret fieldParameters) {
93 for _, part := range strings.Split(str, ",") {
94 switch {
95 case part == "optional":
96 ret.optional = true
97 case part == "explicit":
98 ret.explicit = true
99 if ret.tag == nil {
100 ret.tag = new(int)
101 }
102 case part == "generalized":
103 ret.timeType = TagGeneralizedTime
104 case part == "utc":
105 ret.timeType = TagUTCTime
106 case part == "ia5":
107 ret.stringType = TagIA5String
108 case part == "printable":
109 ret.stringType = TagPrintableString
110 case part == "numeric":
111 ret.stringType = TagNumericString
112 case part == "utf8":
113 ret.stringType = TagUTF8String
114 case strings.HasPrefix(part, "default:"):
115 i, err := strconv.ParseInt(part[8:], 10, 64)
116 if err == nil {
117 ret.defaultValue = new(int64)
118 *ret.defaultValue = i
119 }
120 case strings.HasPrefix(part, "tag:"):
121 i, err := strconv.Atoi(part[4:])
122 if err == nil {
123 ret.tag = new(int)
124 *ret.tag = i
125 }
126 case part == "set":
127 ret.set = true
128 case part == "application":
129 ret.application = true
130 if ret.tag == nil {
131 ret.tag = new(int)
132 }
133 case part == "omitempty":
134 ret.omitEmpty = true
135 }
136 }
137 return
138 }
139
140
141
142 func getUniversalType(t reflect.Type) (matchAny bool, tagNumber int, isCompound, ok bool) {
143 switch t {
144 case rawValueType:
145 return true, -1, false, true
146 case objectIdentifierType:
147 return false, TagOID, false, true
148 case bitStringType:
149 return false, TagBitString, false, true
150 case timeType:
151 return false, TagUTCTime, false, true
152 case enumeratedType:
153 return false, TagEnum, false, true
154 case bigIntType:
155 return false, TagInteger, false, true
156 }
157 switch t.Kind() {
158 case reflect.Bool:
159 return false, TagBoolean, false, true
160 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
161 return false, TagInteger, false, true
162 case reflect.Struct:
163 return false, TagSequence, true, true
164 case reflect.Slice:
165 if t.Elem().Kind() == reflect.Uint8 {
166 return false, TagOctetString, false, true
167 }
168 if strings.HasSuffix(t.Name(), "SET") {
169 return false, TagSet, true, true
170 }
171 return false, TagSequence, true, true
172 case reflect.String:
173 return false, TagPrintableString, false, true
174 }
175 return false, 0, false, false
176 }
177
View as plain text