forked from bojand/ghz
/
data.go
96 lines (81 loc) · 2.14 KB
/
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
package grpcannon
import (
"encoding/json"
"errors"
"github.com/golang/protobuf/jsonpb"
"github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/dynamic"
)
// checks if data is an array / slice of maps
func isArrayData(data interface{}) bool {
arrData, isArrData := data.([]interface{})
if !isArrData {
return false
}
for _, elem := range arrData {
if !isMapData(elem) {
return false
}
}
return true
}
// checks that a data object is a map with string for keys
func isMapData(data interface{}) bool {
_, isArrData := data.(map[string]interface{})
return isArrData
}
// creates a message from a map
// marshal to JSON then use jsonb to marshal to message
// this way we follow protobuf more closely and allow cammelCase properties.
func messageFromMap(input *dynamic.Message, data *map[string]interface{}) error {
strData, err := json.Marshal(data)
if err != nil {
return err
}
err = jsonpb.UnmarshalString(string(strData), input)
if err != nil {
return err
}
return nil
}
func createPayloads(data interface{}, mtd *desc.MethodDescriptor) (*dynamic.Message, *[]*dynamic.Message, error) {
md := mtd.GetInputType()
var input *dynamic.Message
var streamInput []*dynamic.Message
// payload
if isArrayData(data) {
data := data.([]interface{})
elems := len(data)
if elems > 0 {
streamInput = make([]*dynamic.Message, elems)
}
for i, elem := range data {
o := elem.(map[string]interface{})
elemMsg := dynamic.NewMessage(md)
err := messageFromMap(elemMsg, &o)
if err != nil {
return nil, nil, err
}
streamInput[i] = elemMsg
}
} else if isMapData(data) {
input = dynamic.NewMessage(md)
data := data.(map[string]interface{})
err := messageFromMap(input, &data)
if err != nil {
return nil, nil, err
}
} else {
return nil, nil, errors.New("Unsupported type for Data")
}
if mtd.IsClientStreaming() && len(streamInput) == 0 && input != nil {
streamInput = make([]*dynamic.Message, 1)
streamInput[0] = input
input = nil
}
if !mtd.IsClientStreaming() && input == nil && len(streamInput) > 0 {
input = streamInput[0]
streamInput = nil
}
return input, &streamInput, nil
}