-
Notifications
You must be signed in to change notification settings - Fork 217
/
event_data.go
135 lines (119 loc) · 2.94 KB
/
event_data.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
package cloudevents
import (
"context"
"encoding/base64"
"errors"
"fmt"
"strconv"
"github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec"
)
// Data is special. Break it out into it's own file.
// SetData implements EventWriter.SetData
func (e *Event) SetData(obj interface{}) error {
if e.SpecVersion() != CloudEventsVersionV1 {
return e.legacySetData(obj)
}
// Version 1.0 and above.
// TODO: we will have to be smarter about how data relates to media type.
// but the issue is we can not just encode data anymore without understanding
// what the encoding will be on the outbound event. Structured will use
// data_base64, binary will not (if the transport supports binary mode).
// TODO: look at content encoding too.
switch obj.(type) {
case []byte:
e.Data = obj
e.DataEncoded = true
e.DataBinary = true
default:
data, err := datacodec.Encode(context.Background(), e.DataMediaType(), obj)
if err != nil {
return err
}
e.Data = data
e.DataEncoded = true
e.DataBinary = false
}
return nil
}
func (e *Event) legacySetData(obj interface{}) error {
data, err := datacodec.Encode(context.Background(), e.DataMediaType(), obj)
if err != nil {
return err
}
if e.DeprecatedDataContentEncoding() == Base64 {
buf := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
base64.StdEncoding.Encode(buf, data)
e.Data = string(buf)
} else {
e.Data = data
}
e.DataEncoded = true
return nil
}
func (e *Event) DataBytes() ([]byte, error) {
if !e.DataEncoded {
if err := e.SetData(e.Data); err != nil {
return nil, err
}
}
b, ok := e.Data.([]byte)
if !ok {
if s, ok := e.Data.(string); ok {
b = []byte(s)
} else {
// No data.
return []byte(nil), nil
}
}
return b, nil
}
const (
quotes = `"'`
)
// DataAs attempts to populate the provided data object with the event payload.
// data should be a pointer type.
func (e Event) DataAs(data interface{}) error { // TODO: Clean this function up
if e.Data == nil {
return nil
}
obj, ok := e.Data.([]byte)
if !ok {
if s, ok := e.Data.(string); ok {
obj = []byte(s)
} else {
return errors.New("data was not a byte slice or string")
}
}
if len(obj) == 0 {
// No data.
return nil
}
if e.Context.DeprecatedGetDataContentEncoding() == Base64 {
var bs []byte
// test to see if we need to unquote the data.
if obj[0] == quotes[0] || obj[0] == quotes[1] {
str, err := strconv.Unquote(string(obj))
if err != nil {
return err
}
bs = []byte(str)
} else {
bs = obj
}
buf := make([]byte, base64.StdEncoding.DecodedLen(len(bs)))
n, err := base64.StdEncoding.Decode(buf, bs)
if err != nil {
return fmt.Errorf("failed to decode data from base64: %s", err.Error())
}
obj = buf[:n]
}
mediaType := ""
if e.Context.GetDataContentType() != "" {
var err error
mediaType, err = e.Context.GetDataMediaType()
if err != nil {
return err
}
}
return datacodec.Decode(context.Background(), mediaType, obj, data)
}