forked from ThalesGroup/kmip-go
/
types.go
191 lines (164 loc) · 4.58 KB
/
types.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
package ttlv
import (
"io"
"time"
)
func RegisterTypes(r *Registry) {
var m = map[string]Type{
"BigInteger": TypeBigInteger,
"Boolean": TypeBoolean,
"ByteString": TypeByteString,
"DateTime": TypeDateTime,
"Enumeration": TypeEnumeration,
"Integer": TypeInteger,
"Interval": TypeInterval,
"LongInteger": TypeLongInteger,
"Structure": TypeStructure,
"TextString": TypeTextString,
"DateTimeExtended": TypeDateTimeExtended,
}
for name, v := range m {
r.RegisterType(v, name)
}
}
// Type describes the type of a KMIP TTLV.
// 2 and 9.1.1.2
type Type byte
const (
TypeStructure Type = 0x01
TypeInteger Type = 0x02
TypeLongInteger Type = 0x03
TypeBigInteger Type = 0x04
TypeEnumeration Type = 0x05
TypeBoolean Type = 0x06
TypeTextString Type = 0x07
TypeByteString Type = 0x08
TypeDateTime Type = 0x09
TypeInterval Type = 0x0A
TypeDateTimeExtended Type = 0x0B
)
// String returns the normalized name of the type. If the type
// name isn't registered, it returns the hex value of the type,
// e.g. "0x01" (TypeStructure). The value of String() is suitable
// for use in the JSON or XML encoding of TTLV.
func (t Type) String() string {
return DefaultRegistry.FormatType(t)
}
func (t Type) MarshalText() (text []byte, err error) {
return []byte(t.String()), nil
}
func (t *Type) UnmarshalText(text []byte) (err error) {
*t, err = DefaultRegistry.ParseType(string(text))
return
}
// DateTimeExtended is a time wrapper which always marshals to a DateTimeExtended.
type DateTimeExtended struct {
time.Time
}
func (t *DateTimeExtended) UnmarshalTTLV(d *Decoder, ttlv TTLV) error {
if len(ttlv) == 0 {
return nil
}
if t == nil {
*t = DateTimeExtended{}
}
err := d.DecodeValue(&t.Time, ttlv)
if err != nil {
return err
}
return nil
}
func (t DateTimeExtended) MarshalTTLV(e *Encoder, tag Tag) error {
e.EncodeDateTimeExtended(tag, t.Time)
return nil
}
// Value is a go-typed mapping for a TTLV value. It holds a tag, and the value in
// the form of a native go type.
//
// Value supports marshaling and unmarshaling, allowing a mapping between encoded TTLV
// bytes and native go types. It's useful in tests, or where you want to construct
// an arbitrary TTLV structure in code without declaring a bespoke type, e.g.:
//
// v := ttlv.Value{Tag: TagBatchCount, Value: Values{
// Value{Tag: TagComment, Value: "red"},
// Value{Tag: TagComment, Value: "blue"},
// Value{Tag: TagComment, Value: "green"},
// }
// t, err := ttlv.Marshal(v)
//
// KMIP Structure types are mapped to the Values go type. When marshaling, if the Value
// field is set to a Values{}, the resulting TTLV will be TypeStructure. When unmarshaling
// a TTLV with TypeStructure, the Value field will be set to a Values{}.
type Value struct {
Tag Tag
Value interface{}
}
// UnmarshalTTLV implements Unmarshaler
func (t *Value) UnmarshalTTLV(d *Decoder, ttlv TTLV) error {
t.Tag = ttlv.Tag()
switch ttlv.Type() {
case TypeStructure:
var v Values
ttlv = ttlv.ValueStructure()
for ttlv.Valid() == nil {
err := d.DecodeValue(&v, ttlv)
if err != nil {
return err
}
ttlv = ttlv.Next()
}
t.Value = v
default:
t.Value = ttlv.Value()
}
return nil
}
// MarshalTTLV implements Marshaler
func (t Value) MarshalTTLV(e *Encoder, tag Tag) error {
// if tag is set, override the suggested tag
if t.Tag != TagNone {
tag = t.Tag
}
if tvs, ok := t.Value.(Values); ok {
return e.EncodeStructure(tag, func(e *Encoder) error {
for _, v := range tvs {
if err := e.Encode(v); err != nil {
return err
}
}
return nil
})
}
return e.EncodeValue(tag, t.Value)
}
// Values is a slice of Value objects. It represents the body of a TTLV with a type of Structure.
type Values []Value
// NewValue creates a new tagged value.
func NewValue(tag Tag, val interface{}) Value {
return Value{
Tag: tag,
Value: val,
}
}
// NewStruct creates a new tagged value which is of type struct.
func NewStruct(tag Tag, vals ...Value) Value {
return Value{
Tag: tag,
Value: Values(vals),
}
}
type Encoder struct {
encodeDepth int
w io.Writer
encBuf encBuf
// these fields store where the encoder is when marshaling a nested struct. its
// used to construct error messages.
currStruct string
currField string
}
// EnumValue is a uint32 wrapper which always encodes as an enumeration.
type EnumValue uint32
func (v EnumValue) MarshalTTLV(e *Encoder, tag Tag) error {
e.EncodeEnumeration(tag, uint32(v))
return nil
}