This repository has been archived by the owner on Mar 18, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
cbor.go
153 lines (143 loc) · 3.99 KB
/
cbor.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
package cbor
import (
"bytes"
"encoding"
"fmt"
"reflect"
)
// Encoder is an interface for types that know how to turn themselfes into cbor
type Encoder interface {
EncodeCBOR() []byte
}
// Marshaler is an interface (derived from encoding.*Marshaler) for types that know how to turn themselfes into cbor (encoding will panic when error is not nil)
type Marshaler interface {
MarshalCBOR() ([]byte, error)
}
var (
tagMap map[uint64]func(interface{}) (interface{}, error)
// Types used to check for interface implementations
cborEncoder reflect.Type = reflect.TypeOf((*Encoder)(nil)).Elem()
cborMarshaler reflect.Type = reflect.TypeOf((*Marshaler)(nil)).Elem()
binaryMarshaler reflect.Type = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem()
textMarshaler reflect.Type = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
)
func init() {
tagMap = make(map[uint64]func(interface{}) (interface{}, error))
}
// Encode encodes an arbitrary type or data structure as a cbor value
func Encode(in interface{}) []byte {
return encode(in)
}
func encode(in interface{}) []byte {
val := reflect.ValueOf(in)
t := reflect.TypeOf(in)
if t.Implements(cborEncoder) {
return in.(Encoder).EncodeCBOR()
}
if t.Implements(cborMarshaler) {
b, err := in.(Marshaler).MarshalCBOR()
if err != nil {
panic(err)
}
return b
}
if t.Implements(binaryMarshaler) {
b, err := in.(encoding.BinaryMarshaler).MarshalBinary()
if err != nil {
panic(err)
}
return EncodeBytes(b)
}
switch val.Kind() {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return EncodeUint(val.Uint())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return EncodeInt(val.Int())
case reflect.Float32, reflect.Float64:
return EncodeFloat(val.Float())
case reflect.String:
return EncodeString(val.String())
case reflect.Slice:
if reflect.TypeOf(in) == reflect.TypeOf([]byte{0x00}) {
return EncodeBytes(val.Bytes())
}
return EncodeArray(in)
case reflect.Array:
if val.Len() > 0 && reflect.TypeOf(val.Index(0)) == reflect.TypeOf([]byte{0x00}) {
s := val.Slice(0, val.Len())
return EncodeBytes(s.Bytes())
}
return EncodeArray(in)
case reflect.Map:
return EncodeMap(in)
case reflect.Bool:
if val.Bool() {
return []byte{0xF5}
}
return []byte{0xF4}
case reflect.Ptr, reflect.Interface:
return encode(val.Elem().Interface())
case reflect.Struct:
return EncodeStruct(in)
}
if t.Implements(textMarshaler) {
s, err := in.(encoding.TextMarshaler).MarshalText()
if err != nil {
panic(err)
}
return EncodeString(string(s))
}
panic(fmt.Sprintf("encode fell trough: cannot encode type %s\nif it is a custom type make sure it implements a supported encoding interface\notherwise consult the README and open an issue if this type is not listed as unsupported there\n", reflect.TypeOf(in)))
}
// Decode decodes a cbor value to an arbitrary type or data structure
func Decode(in []byte) (interface{}, error) {
r := bytes.NewReader(in)
for fb, err := r.ReadByte(); err == nil; {
return decode(fb, r)
}
return nil, nil
}
func decode(fb byte, r *bytes.Reader) (interface{}, error) {
major := fb >> 5
switch major {
case 0:
return DecodeUint(fb, r)
case 1:
return DecodeInt(fb, r)
case 2:
return DecodeBytes(fb, r)
case 3:
return DecodeString(fb, r)
case 4:
return DecodeArray(fb, r)
case 5:
return DecodeMap(fb, r)
case 6:
return DecodeTag(fb, r)
case 7:
additional := fb & 0x1F
switch additional {
case 20:
return false, nil
case 21:
return true, nil
case 22:
return nil, nil
case 23:
return nil, nil
case 24:
return DecodeSimple(fb, r)
case 25:
return DecodeFloat16(fb, r)
case 26:
return DecodeFloat32(fb, r)
case 27:
return DecodeFloat64(fb, r)
case 31:
return nil, fmt.Errorf("unexpected break outside an indefinite length element")
default:
return nil, fmt.Errorf("simple value %d is not assigned in RFC7049", additional)
}
}
return nil, nil // This will never be reached
}